Source Code
Latest 25 from a total of 29,444 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| 0x44656172 | 17502498 | 973 days ago | IN | 0 ETH | 0.0007688 | ||||
| Mooo Z1089603480 | 13095034 | 1635 days ago | IN | 0 ETH | 0.09908834 | ||||
| Mooo Z1089603480 | 13094675 | 1635 days ago | IN | 0 ETH | 0.04165064 | ||||
| Mooo Z1089603480 | 13093954 | 1635 days ago | IN | 0 ETH | 0.26569658 | ||||
| Mooo Z1089603480 | 13093899 | 1635 days ago | IN | 0 ETH | 0.21237904 | ||||
| Mooo Z1089603480 | 13093849 | 1635 days ago | IN | 0 ETH | 0.23907085 | ||||
| Mooo Z1089603480 | 13093752 | 1635 days ago | IN | 0 ETH | 0.22923769 | ||||
| Mooo Z1089603480 | 13003298 | 1649 days ago | IN | 0 ETH | 0.01734255 | ||||
| Mooo Z1089603480 | 13003297 | 1649 days ago | IN | 0 ETH | 0.01361376 | ||||
| Mooo Z1089603480 | 13003277 | 1649 days ago | IN | 0 ETH | 0.01229603 | ||||
| Mooo Z1089603480 | 13003264 | 1649 days ago | IN | 0 ETH | 0.01094576 | ||||
| Mooo Z1089603480 | 13003257 | 1649 days ago | IN | 0 ETH | 0.02104441 | ||||
| Mooo Z1089603480 | 13003224 | 1649 days ago | IN | 0 ETH | 0.01156496 | ||||
| Mooo Z1089603480 | 13003167 | 1649 days ago | IN | 0 ETH | 0.03462601 | ||||
| Mooo Z1089603480 | 13003162 | 1649 days ago | IN | 0 ETH | 0.00803047 | ||||
| Mooo Z1089603480 | 13003148 | 1649 days ago | IN | 0 ETH | 0.04317549 | ||||
| Mooo Z1089603480 | 13003137 | 1649 days ago | IN | 0 ETH | 0.01423285 | ||||
| Mooo Z1089603480 | 13003126 | 1649 days ago | IN | 0 ETH | 0.01652458 | ||||
| Mooo Z1089603480 | 13003115 | 1649 days ago | IN | 0 ETH | 0.0292176 | ||||
| Mooo Z1089603480 | 13003098 | 1649 days ago | IN | 0 ETH | 0.01954801 | ||||
| Mooo Z1089603480 | 13003077 | 1649 days ago | IN | 0 ETH | 0.01738316 | ||||
| Mooo Z1089603480 | 13003075 | 1649 days ago | IN | 0 ETH | 0.02864128 | ||||
| Mooo Z1089603480 | 13003041 | 1649 days ago | IN | 0 ETH | 0.03269788 | ||||
| Mooo Z1089603480 | 13002938 | 1649 days ago | IN | 0 ETH | 0.01788976 | ||||
| Mooo Z1089603480 | 13002911 | 1649 days ago | IN | 0 ETH | 0.01142833 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 13199318 | 1619 days ago | 0.01 ETH | ||||
| - | 13145734 | 1627 days ago | 0.0052191 ETH | ||||
| - | 13002938 | 1649 days ago | 0.45608028 ETH | ||||
| - | 13002938 | 1649 days ago | 0.45608028 ETH | ||||
| - | 13002911 | 1649 days ago | 0.18392151 ETH | ||||
| - | 13002911 | 1649 days ago | 0.18392151 ETH | ||||
| - | 13002893 | 1649 days ago | 55.54155438 ETH | ||||
| - | 13002893 | 1649 days ago | 55.54155438 ETH | ||||
| - | 13002831 | 1649 days ago | 124.45029551 ETH | ||||
| - | 13002831 | 1649 days ago | 124.45029551 ETH | ||||
| - | 13002665 | 1649 days ago | 0.01419992 ETH | ||||
| - | 13002665 | 1649 days ago | 0.01419992 ETH | ||||
| - | 13002619 | 1649 days ago | 14.31975221 ETH | ||||
| - | 13002619 | 1649 days ago | 14.31975221 ETH | ||||
| - | 13002558 | 1649 days ago | 2 ETH | ||||
| - | 13002558 | 1649 days ago | 2 ETH | ||||
| - | 13002538 | 1649 days ago | 0.07287646 ETH | ||||
| - | 13002538 | 1649 days ago | 0.07287646 ETH | ||||
| - | 13002532 | 1649 days ago | 0.43708298 ETH | ||||
| - | 13002532 | 1649 days ago | 0.43708298 ETH | ||||
| - | 13002527 | 1649 days ago | 2.58208246 ETH | ||||
| - | 13002527 | 1649 days ago | 2.58208246 ETH | ||||
| - | 13002510 | 1649 days ago | 0.32 ETH | ||||
| - | 13002510 | 1649 days ago | 0.32 ETH | ||||
| - | 13002476 | 1649 days ago | 0.94808559 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
GPv2Settlement
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
pragma abicoder v2;
import "@gnosis.pm/util-contracts/contracts/StorageAccessible.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./GPv2AllowanceManager.sol";
import "./interfaces/GPv2Authentication.sol";
import "./libraries/GPv2Interaction.sol";
import "./libraries/GPv2Order.sol";
import "./libraries/GPv2Trade.sol";
import "./libraries/GPv2TradeExecution.sol";
import "./mixins/GPv2Signing.sol";
/// @title Gnosis Protocol v2 Settlement Contract
/// @author Gnosis Developers
contract GPv2Settlement is GPv2Signing, ReentrancyGuard, StorageAccessible {
using GPv2Order for bytes;
using GPv2TradeExecution for GPv2TradeExecution.Data;
using SafeMath for uint256;
/// @dev The authenticator is used to determine who can call the settle function.
/// That is, only authorised solvers have the ability to invoke settlements.
/// Any valid authenticator implements an isSolver method called by the onlySolver
/// modifier below.
GPv2Authentication public immutable authenticator;
/// @dev The allowance manager which has access to order funds. This
/// contract is created during deployment
GPv2AllowanceManager public immutable allowanceManager;
/// @dev Map each user order by UID to the amount that has been filled so
/// far. If this amount is larger than or equal to the amount traded in the
/// order (amount sold for sell orders, amount bought for buy orders) then
/// the order cannot be traded anymore. If the order is fill or kill, then
/// this value is only used to determine whether the order has already been
/// executed.
mapping(bytes => uint256) public filledAmount;
/// @dev Event emitted for each executed trade.
event Trade(
address indexed owner,
IERC20 sellToken,
IERC20 buyToken,
uint256 sellAmount,
uint256 buyAmount,
uint256 feeAmount,
bytes orderUid
);
/// @dev Event emitted for each executed interaction.
///
/// For gas effeciency, only the interaction calldata selector (first 4
/// bytes) is included in the event. For interactions without calldata or
/// whose calldata is shorter than 4 bytes, the selector will be `0`.
event Interaction(address indexed target, uint256 value, bytes4 selector);
/// @dev Event emitted when a settlement complets
event Settlement(address indexed solver);
/// @dev Event emitted when an order is invalidated.
event OrderInvalidated(address indexed owner, bytes orderUid);
constructor(GPv2Authentication authenticator_) {
authenticator = authenticator_;
allowanceManager = new GPv2AllowanceManager();
}
// solhint-disable-next-line no-empty-blocks
receive() external payable {
// NOTE: Include an empty receive function so that the settlement
// contract can receive Ether from contract interactions.
}
/// @dev This modifier is called by settle function to block any non-listed
/// senders from settling batches.
modifier onlySolver {
require(authenticator.isSolver(msg.sender), "GPv2: not a solver");
_;
}
/// @dev Modifier to ensure that an external function is only callable as a
/// settlement interaction.
modifier onlyInteraction {
require(address(this) == msg.sender, "GPv2: not an interaction");
_;
}
/// @dev Settle the specified orders at a clearing price. Note that it is
/// the responsibility of the caller to ensure that all GPv2 invariants are
/// upheld for the input settlement, otherwise this call will revert.
/// Namely:
/// - All orders are valid and signed
/// - Accounts have sufficient balance and approval.
/// - Settlement contract has sufficient balance to execute trades. Note
/// this implies that the accumulated fees held in the contract can also
/// be used for settlement. This is OK since:
/// - Solvers need to be authorized
/// - Misbehaving solvers will be slashed for abusing accumulated fees for
/// settlement
/// - Critically, user orders are entirely protected
///
/// @param tokens An array of ERC20 tokens to be traded in the settlement.
/// Trades encode tokens as indices into this array.
/// @param clearingPrices An array of clearing prices where the `i`-th price
/// is for the `i`-th token in the [`tokens`] array.
/// @param trades Trades for signed orders.
/// @param interactions Smart contract interactions split into three
/// separate lists to be run before the settlement, during the settlement
/// and after the settlement respectively.
function settle(
IERC20[] calldata tokens,
uint256[] calldata clearingPrices,
GPv2Trade.Data[] calldata trades,
GPv2Interaction.Data[][3] calldata interactions
) external nonReentrant onlySolver {
executeInteractions(interactions[0]);
GPv2TradeExecution.Data[] memory executedTrades =
computeTradeExecutions(tokens, clearingPrices, trades);
allowanceManager.transferIn(executedTrades);
executeInteractions(interactions[1]);
transferOut(executedTrades);
executeInteractions(interactions[2]);
emit Settlement(msg.sender);
}
/// @dev Invalidate onchain an order that has been signed offline.
///
/// @param orderUid The unique identifier of the order that is to be made
/// invalid after calling this function. The user that created the order
/// must be the the sender of this message. See [`extractOrderUidParams`]
/// for details on orderUid.
function invalidateOrder(bytes calldata orderUid) external {
(, address owner, ) = orderUid.extractOrderUidParams();
require(owner == msg.sender, "GPv2: caller does not own order");
filledAmount[orderUid] = uint256(-1);
emit OrderInvalidated(owner, orderUid);
}
/// @dev Free storage from the filled amounts of **expired** orders to claim
/// a gas refund. This method can only be called as an interaction.
///
/// @param orderUids The unique identifiers of the expired order to free
/// storage for.
function freeFilledAmountStorage(bytes[] calldata orderUids)
external
onlyInteraction
{
freeOrderStorage(filledAmount, orderUids);
}
/// @dev Free storage from the pre signatures of **expired** orders to claim
/// a gas refund. This method can only be called as an interaction.
///
/// @param orderUids The unique identifiers of the expired order to free
/// storage for.
function freePreSignatureStorage(bytes[] calldata orderUids)
external
onlyInteraction
{
freeOrderStorage(preSignature, orderUids);
}
/// @dev Process all trades one at a time returning the computed net in and
/// out transfers for the trades.
///
/// This method reverts if processing of any single trade fails. See
/// [`computeTradeExecution`] for more details.
///
/// @param tokens An array of ERC20 tokens to be traded in the settlement.
/// @param clearingPrices An array of token clearing prices.
/// @param trades Trades for signed orders.
/// @return executedTrades Array of executed trades.
function computeTradeExecutions(
IERC20[] calldata tokens,
uint256[] calldata clearingPrices,
GPv2Trade.Data[] calldata trades
) internal returns (GPv2TradeExecution.Data[] memory executedTrades) {
RecoveredOrder memory recoveredOrder = allocateRecoveredOrder();
executedTrades = new GPv2TradeExecution.Data[](trades.length);
for (uint256 i = 0; i < trades.length; i++) {
GPv2Trade.Data calldata trade = trades[i];
recoverOrderFromTrade(recoveredOrder, tokens, trade);
computeTradeExecution(
recoveredOrder,
clearingPrices[trade.sellTokenIndex],
clearingPrices[trade.buyTokenIndex],
trade.executedAmount,
executedTrades[i]
);
}
}
/// @dev Compute the in and out transfer amounts for a single trade.
/// This function reverts if:
/// - The order has expired
/// - The order's limit price is not respected
/// - The order gets over-filled
/// - The fee discount is larger than the executed fee
///
/// @param recoveredOrder The recovered order to process.
/// @param sellPrice The price of the order's sell token.
/// @param buyPrice The price of the order's buy token.
/// @param executedAmount The portion of the order to execute. This will be
/// ignored for fill-or-kill orders.
/// @param executedTrade Memory location for computed executed trade data.
function computeTradeExecution(
RecoveredOrder memory recoveredOrder,
uint256 sellPrice,
uint256 buyPrice,
uint256 executedAmount,
GPv2TradeExecution.Data memory executedTrade
) internal {
GPv2Order.Data memory order = recoveredOrder.data;
bytes memory orderUid = recoveredOrder.uid;
// solhint-disable-next-line not-rely-on-time
require(order.validTo >= block.timestamp, "GPv2: order expired");
executedTrade.owner = recoveredOrder.owner;
executedTrade.receiver = recoveredOrder.receiver;
executedTrade.sellToken = order.sellToken;
executedTrade.buyToken = order.buyToken;
// NOTE: The following computation is derived from the equation:
// ```
// amount_x * price_x = amount_y * price_y
// ```
// Intuitively, if a chocolate bar is 0,50€ and a beer is 4€, 1 beer
// is roughly worth 8 chocolate bars (`1 * 4 = 8 * 0.5`). From this
// equation, we can derive:
// - The limit price for selling `x` and buying `y` is respected iff
// ```
// limit_x * price_x >= limit_y * price_y
// ```
// - The executed amount of token `y` given some amount of `x` and
// clearing prices is:
// ```
// amount_y = amount_x * price_x / price_y
// ```
require(
order.sellAmount.mul(sellPrice) >= order.buyAmount.mul(buyPrice),
"GPv2: limit price not respected"
);
uint256 executedSellAmount;
uint256 executedBuyAmount;
uint256 executedFeeAmount;
uint256 currentFilledAmount;
// NOTE: Don't use `SafeMath.div` or `SafeMath.sub` anywhere here as it
// allocates a string even if it does not revert. Additionally, `div`
// only checks that the divisor is non-zero and `revert`s in that case
// instead of consuming all of the remaining transaction gas when
// dividing by zero, so no extra checks are needed for those operations.
if (order.kind == GPv2Order.SELL) {
if (order.partiallyFillable) {
executedSellAmount = executedAmount;
executedFeeAmount =
order.feeAmount.mul(executedSellAmount) /
order.sellAmount;
} else {
executedSellAmount = order.sellAmount;
executedFeeAmount = order.feeAmount;
}
executedBuyAmount = executedSellAmount.mul(sellPrice) / buyPrice;
currentFilledAmount = filledAmount[orderUid].add(
executedSellAmount
);
require(
currentFilledAmount <= order.sellAmount,
"GPv2: order filled"
);
} else {
if (order.partiallyFillable) {
executedBuyAmount = executedAmount;
executedFeeAmount =
order.feeAmount.mul(executedBuyAmount) /
order.buyAmount;
} else {
executedBuyAmount = order.buyAmount;
executedFeeAmount = order.feeAmount;
}
executedSellAmount = executedBuyAmount.mul(buyPrice) / sellPrice;
currentFilledAmount = filledAmount[orderUid].add(executedBuyAmount);
require(
currentFilledAmount <= order.buyAmount,
"GPv2: order filled"
);
}
executedTrade.sellAmount = executedSellAmount.add(executedFeeAmount);
executedTrade.buyAmount = executedBuyAmount;
filledAmount[orderUid] = currentFilledAmount;
emit Trade(
executedTrade.owner,
executedTrade.sellToken,
executedTrade.buyToken,
executedTrade.sellAmount,
executedTrade.buyAmount,
executedFeeAmount,
orderUid
);
}
/// @dev Execute a list of arbitrary contract calls from this contract.
/// @param interactions The list of interactions to execute.
function executeInteractions(GPv2Interaction.Data[] calldata interactions)
internal
{
for (uint256 i; i < interactions.length; i++) {
GPv2Interaction.Data calldata interaction = interactions[i];
// To prevent possible attack on user funds, we explicitly disable
// any interactions with AllowanceManager contract.
require(
interaction.target != address(allowanceManager),
"GPv2: forbidden interaction"
);
GPv2Interaction.execute(interaction);
emit Interaction(
interaction.target,
interaction.value,
GPv2Interaction.selector(interaction)
);
}
}
/// @dev Transfers all buy amounts for the executed trades from the
/// settlement contract to the order owners. This function reverts if any of
/// the ERC20 operations fail.
///
/// @param trades The executed trades whose buy amounts need to be
/// transferred out.
function transferOut(GPv2TradeExecution.Data[] memory trades) internal {
for (uint256 i = 0; i < trades.length; i++) {
trades[i].transferBuyAmountToOwner();
}
}
/// @dev Claims refund for the specified storage and order UIDs.
///
/// This method reverts if any of the orders are still valid.
///
/// @param orderUids Order refund data for freeing storage.
/// @param orderStorage Order storage mapped on a UID.
function freeOrderStorage(
mapping(bytes => uint256) storage orderStorage,
bytes[] calldata orderUids
) internal {
for (uint256 i = 0; i < orderUids.length; i++) {
bytes calldata orderUid = orderUids[i];
(, , uint32 validTo) = orderUid.extractOrderUidParams();
// solhint-disable-next-line not-rely-on-time
require(validTo < block.timestamp, "GPv2: order still valid");
orderStorage[orderUid] = 0;
}
}
}// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.7.0;
/// @title ViewStorageAccessible - Interface on top of StorageAccessible base class to allow simulations from view functions
interface ViewStorageAccessible {
/**
* @dev Same as `simulateDelegatecall` on StorageAccessible. Marked as view so that it can be called from external contracts
* that want to run simulations from within view functions. Will revert if the invoked simulation attempts to change state.
*/
function simulateDelegatecall(
address targetContract,
bytes memory calldataPayload
) external view returns (bytes memory);
/**
* @dev Same as `getStorageAt` on StorageAccessible. This method allows reading aribtrary ranges of storage.
*/
function getStorageAt(uint256 offset, uint256 length)
external
view
returns (bytes memory);
}
/// @title StorageAccessible - generic base contract that allows callers to access all internal storage.
contract StorageAccessible {
/**
* @dev Reads `length` bytes of storage in the currents contract
* @param offset - the offset in the current contract's storage in words to start reading from
* @param length - the number of words (32 bytes) of data to read
* @return the bytes that were read.
*/
function getStorageAt(uint256 offset, uint256 length)
external
view
returns (bytes memory)
{
bytes memory result = new bytes(length * 32);
for (uint256 index = 0; index < length; index++) {
assembly {
let word := sload(add(offset, index))
mstore(add(add(result, 0x20), mul(index, 0x20)), word)
}
}
return result;
}
/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static). Catches revert and returns encoded result as bytes.
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateDelegatecall(
address targetContract,
bytes memory calldataPayload
) public returns (bytes memory response) {
bytes memory innerCall = abi.encodeWithSelector(
this.simulateDelegatecallInternal.selector,
targetContract,
calldataPayload
);
(, response) = address(this).call(innerCall);
bool innerSuccess = response[response.length - 1] == 0x01;
setLength(response, response.length - 1);
if (innerSuccess) {
return response;
} else {
revertWith(response);
}
}
/**
* @dev Performs a delegetecall on a targetContract in the context of self.
* Internally reverts execution to avoid side effects (making it static). Returns encoded result as revert message
* concatenated with the success flag of the inner call as a last byte.
* @param targetContract Address of the contract containing the code to execute.
* @param calldataPayload Calldata that should be sent to the target contract (encoded method name and arguments).
*/
function simulateDelegatecallInternal(
address targetContract,
bytes memory calldataPayload
) external returns (bytes memory response) {
bool success;
(success, response) = targetContract.delegatecall(
calldataPayload
);
revertWith(abi.encodePacked(response, success));
}
function revertWith(bytes memory response) internal pure {
assembly {
revert(add(response, 0x20), mload(response))
}
}
function setLength(bytes memory buffer, uint256 length) internal pure {
assembly {
mstore(buffer, length)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./libraries/GPv2TradeExecution.sol";
/// @title Gnosis Protocol v2 Allowance Manager Contract
/// @author Gnosis Developers
contract GPv2AllowanceManager {
using GPv2TradeExecution for GPv2TradeExecution.Data;
/// @dev The recipient of all transfers made by the allowance manager. The
/// recipient is set at creation time and cannot change.
address private immutable recipient;
constructor() {
recipient = msg.sender;
}
/// @dev Modifier that ensures that a function can only be called by the
/// recipient of this contract.
modifier onlyRecipient {
require(msg.sender == recipient, "GPv2: not allowance recipient");
_;
}
/// @dev Transfers all sell amounts for the executed trades from their
/// owners to the caller.
///
/// This function reverts if:
/// - The caller is not the recipient of the allowance manager
/// - Any ERC20 transfer fails
///
/// @param trades The executed trades whose sell amounts need to be
/// transferred in.
function transferIn(GPv2TradeExecution.Data[] calldata trades)
external
onlyRecipient
{
for (uint256 i = 0; i < trades.length; i++) {
GPv2TradeExecution.transferSellAmountToRecipient(
trades[i],
msg.sender
);
}
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
/// @title Gnosis Protocol v2 Authentication Interface
/// @author Gnosis Developers
interface GPv2Authentication {
/// @dev determines whether the provided address is an authenticated solver.
/// @param prospectiveSolver the address of prospective solver.
/// @return true when prospectiveSolver is an authenticated solver, otherwise false.
function isSolver(address prospectiveSolver) external view returns (bool);
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
library GPv2EIP1271 {
/// @dev Value returned by a call to `isValidSignature` if the signature
/// was verified successfully. The value is defined in EIP-1271 as:
/// bytes4(keccak256("isValidSignature(bytes32,bytes)"))
bytes4 internal constant MAGICVALUE = 0x1626ba7e;
}
/// @title EIP1271 Interface
/// @dev Standardized interface for an implementation of smart contract
/// signatures as described in EIP-1271. The code that follows is identical to
/// the code in the standard with the exception of formatting and syntax
/// changes to adapt the code to our Solidity version.
interface EIP1271Verifier {
/// @dev Should return whether the signature provided is valid for the
/// provided data
/// @param _hash Hash of the data to be signed
/// @param _signature Signature byte array associated with _data
///
/// MUST return the bytes4 magic value 0x1626ba7e when function passes.
/// MUST NOT modify state (using STATICCALL for solc < 0.5, view modifier for
/// solc > 0.5)
/// MUST allow external calls
///
function isValidSignature(bytes32 _hash, bytes memory _signature)
external
view
returns (bytes4 magicValue);
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
/// @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-or-later
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/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;
}
/// @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" +
/// ")"
/// )
/// ```
bytes32 internal constant TYPE_HASH =
hex"d604be04a8c6d2df582ec82eba9b65ce714008acbf9122dd95e499569c8f1a80";
/// @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 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 BUY =
hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";
/// @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 10 fields, and
// including the type hash `(10 + 1) * 32 = 352` 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, 352)
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: LGPL-3.0-or-later
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title Gnosis Protocol v2 Safe ERC20 Transfer Library
/// @author Gnosis Developers
/// @dev Gas-efficient version of Openzeppelin's SafeERC20 contract that notably
/// does not revert when calling a non-contract.
library GPv2SafeERC20 {
/// @dev Wrapper around a call to the ERC20 function `transfer` that reverts
/// also when the token returns `false`.
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
bytes4 selector_ = token.transfer.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(
add(freeMemoryPointer, 4),
and(to, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(add(freeMemoryPointer, 36), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTansferResult(), "GPv2: failed transfer");
}
/// @dev Wrapper around a call to the ERC20 function `transferFrom` that
/// reverts also when the token returns `false`.
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
bytes4 selector_ = token.transferFrom.selector;
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, selector_)
mstore(
add(freeMemoryPointer, 4),
and(from, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(
add(freeMemoryPointer, 36),
and(to, 0xffffffffffffffffffffffffffffffffffffffff)
)
mstore(add(freeMemoryPointer, 68), value)
if iszero(call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
require(getLastTansferResult(), "GPv2: failed transferFrom");
}
/// @dev Verifies that the last return was a successful `transfer*` call.
/// This is done by checking that the return data is either empty, or
/// is a valid ABI encoded boolean.
function getLastTansferResult() private pure returns (bool success) {
bool badReturnSize;
// NOTE: Inspecting previous return data requires assembly. Note that
// we write the return data to memory 0 in the case where the return
// data size is 32, this is OK since the first 64 bytes of memory are
// reserved by Solidy as a scratch space that can be used within
// assembly blocks.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html>
// solhint-disable-next-line no-inline-assembly
assembly {
switch returndatasize()
// Non-standard ERC20 transfer without return.
case 0 {
success := 1
}
// Standard ERC20 transfer returning boolean success value.
case 32 {
returndatacopy(0, 0, returndatasize())
// NOTE: For ABI encoding v1, any non-zero value is accepted
// as `true` for a boolean. In order to stay compatible with
// OpenZeppelin's `SafeERC20` library which is known to work
// with the existing ERC20 implementation we care about,
// make sure we return success for any non-zero return value
// from the `transfer*` call.
success := iszero(iszero(mload(0)))
}
default {
badReturnSize := 1
}
}
require(!badReturnSize, "GPv2: malformed transfer result");
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../mixins/GPv2Signing.sol";
import "./GPv2Order.sol";
/// @title Gnosis Protocol v2 Trade Library.
/// @author Gnosis Developers
library GPv2Trade {
using GPv2Order for GPv2Order.Data;
using GPv2Order for bytes;
/// @dev A struct representing a trade to be executed as part a batch
/// settlement.
struct Data {
uint256 sellTokenIndex;
uint256 buyTokenIndex;
address receiver;
uint256 sellAmount;
uint256 buyAmount;
uint32 validTo;
bytes32 appData;
uint256 feeAmount;
uint256 flags;
uint256 executedAmount;
bytes signature;
}
/// @dev Extracts the order data and signing scheme for the specified trade.
///
/// @param trade The trade.
/// @param tokens The list of tokens included in the settlement. The token
/// indices in the trade parameters map to tokens in this array.
/// @param order The memory location to extract the order data to.
function extractOrder(
Data calldata trade,
IERC20[] calldata tokens,
GPv2Order.Data memory order
) internal pure returns (GPv2Signing.Scheme signingScheme) {
order.sellToken = tokens[trade.sellTokenIndex];
order.buyToken = tokens[trade.buyTokenIndex];
order.receiver = trade.receiver;
order.sellAmount = trade.sellAmount;
order.buyAmount = trade.buyAmount;
order.validTo = trade.validTo;
order.appData = trade.appData;
order.feeAmount = trade.feeAmount;
(order.kind, order.partiallyFillable, signingScheme) = extractFlags(
trade.flags
);
}
/// @dev Decodes trade flags.
///
/// Trade flags are used to tightly encode information on how to decode
/// an order. Examples that directly affect the structure of an order are
/// the kind of order (either a sell or a buy order) as well as whether the
/// order is partially fillable or if it is a "fill-or-kill" order. It also
/// encodes the signature scheme used to validate the order. As the most
/// likely values are fill-or-kill sell orders by an externally owned
/// account, the flags are chosen such that `0x00` represents this kind of
/// order. The flags byte uses the following format:
///
/// ```
/// bit | 31 ... 4 | 3 | 2 | 1 | 0 |
/// ----+----------+-------+---+---+
/// | reserved | * * | * | * |
/// | | | |
/// | | | +---- order kind bit, 0 for a sell order
/// | | | and 1 for a buy order
/// | | |
/// | | +-------- order fill bit, 0 for fill-or-kill
/// | | and 1 for a partially fillable order
/// | |
/// +---+------------ signature scheme bits:
/// 00: EIP-712
/// 01: eth_sign
/// 10: EIP-1271
/// 11: pre_sign
/// ```
function extractFlags(uint256 flags)
internal
pure
returns (
bytes32 kind,
bool partiallyFillable,
GPv2Signing.Scheme signingScheme
)
{
if (flags & 0x01 == 0) {
kind = GPv2Order.SELL;
} else {
kind = GPv2Order.BUY;
}
partiallyFillable = flags & 0x02 != 0;
// NOTE: Take advantage of the fact that Solidity will revert if the
// following expression does not produce a valid enum value. This means
// we check here that the leading reserved bits must be 0.
signingScheme = GPv2Signing.Scheme(flags >> 2);
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./GPv2SafeERC20.sol";
/// @title Gnosis Protocol v2 Trade Execution
/// @author Gnosis Developers
library GPv2TradeExecution {
using GPv2SafeERC20 for IERC20;
/// @dev Executed trade data.
struct Data {
address owner;
address receiver;
IERC20 sellToken;
IERC20 buyToken;
uint256 sellAmount;
uint256 buyAmount;
}
/// @dev Ether marker address used to indicate an order is buying Ether.
address internal constant BUY_ETH_ADDRESS =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev Executes the trade's sell amount, transferring it from the trade's
/// owner to the specified recipient.
function transferSellAmountToRecipient(
Data calldata trade,
address recipient
) internal {
require(
address(trade.sellToken) != BUY_ETH_ADDRESS,
"GPv2: cannot transfer native ETH"
);
trade.sellToken.safeTransferFrom(
trade.owner,
recipient,
trade.sellAmount
);
}
/// @dev Executes the trade's buy amount, transferring it to the trade's
/// receiver from the caller's address.
function transferBuyAmountToOwner(Data memory trade) internal {
if (address(trade.buyToken) == BUY_ETH_ADDRESS) {
payable(trade.receiver).transfer(trade.buyAmount);
} else {
trade.buyToken.safeTransfer(trade.receiver, trade.buyAmount);
}
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.7.6;
import "../interfaces/GPv2EIP1271.sol";
import "../libraries/GPv2Order.sol";
import "../libraries/GPv2Trade.sol";
/// @title Gnosis Protocol v2 Signing Library.
/// @author Gnosis Developers
abstract contract GPv2Signing {
using GPv2Order for GPv2Order.Data;
using GPv2Order for bytes;
/// @dev Recovered trade data containing the extracted order and the
/// recovered owner address.
struct RecoveredOrder {
GPv2Order.Data data;
bytes uid;
address owner;
address receiver;
}
/// @dev Signing scheme used for recovery.
enum Scheme {Eip712, EthSign, Eip1271, PreSign}
/// @dev The EIP-712 domain type hash used for computing the domain
/// separator.
bytes32 private constant DOMAIN_TYPE_HASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
/// @dev The EIP-712 domain name used for computing the domain separator.
bytes32 private constant DOMAIN_NAME = keccak256("Gnosis Protocol");
/// @dev The EIP-712 domain version used for computing the domain separator.
bytes32 private constant DOMAIN_VERSION = keccak256("v2");
/// @dev Marker value indicating an order is pre-signed.
uint256 private constant PRE_SIGNED =
uint256(keccak256("GPv2Signing.Scheme.PreSign"));
/// @dev The domain separator used for signing orders that gets mixed in
/// making signatures for different domains incompatible. This domain
/// separator is computed following the EIP-712 standard and has replay
/// protection mixed in so that signed orders are only valid for specific
/// GPv2 contracts.
bytes32 public immutable domainSeparator;
/// @dev Storage indicating whether or not an order has been signed by a
/// particular address.
mapping(bytes => uint256) public preSignature;
/// @dev Event that is emitted when an account either pre-signs an order or
/// revokes an existing pre-signature.
event PreSignature(address indexed owner, bytes orderUid, bool signed);
constructor() {
// NOTE: Currently, the only way to get the chain ID in solidity is
// using assembly.
uint256 chainId;
// solhint-disable-next-line no-inline-assembly
assembly {
chainId := chainid()
}
domainSeparator = keccak256(
abi.encode(
DOMAIN_TYPE_HASH,
DOMAIN_NAME,
DOMAIN_VERSION,
chainId,
address(this)
)
);
}
/// @dev Sets a presignature for the specified order UID.
///
/// @param orderUid The unique identifier of the order to pre-sign.
function setPreSignature(bytes calldata orderUid, bool signed) external {
(, address owner, ) = orderUid.extractOrderUidParams();
require(owner == msg.sender, "GPv2: cannot presign order");
if (signed) {
preSignature[orderUid] = PRE_SIGNED;
} else {
preSignature[orderUid] = 0;
}
emit PreSignature(owner, orderUid, signed);
}
/// @dev Returns an empty recovered order with a pre-allocated buffer for
/// packing the unique identifier.
///
/// @return recoveredOrder The empty recovered order data.
function allocateRecoveredOrder()
internal
pure
returns (RecoveredOrder memory recoveredOrder)
{
recoveredOrder.uid = new bytes(GPv2Order.UID_LENGTH);
}
/// @dev Extracts order data and recovers the signer from the specified
/// trade.
///
/// @param recoveredOrder Memory location used for writing the recovered order data.
/// @param tokens The list of tokens included in the settlement. The token
/// indices in the trade parameters map to tokens in this array.
/// @param trade The trade data to recover the order data from.
function recoverOrderFromTrade(
RecoveredOrder memory recoveredOrder,
IERC20[] calldata tokens,
GPv2Trade.Data calldata trade
) internal view {
GPv2Order.Data memory order = recoveredOrder.data;
Scheme signingScheme = GPv2Trade.extractOrder(trade, tokens, order);
(bytes32 orderDigest, address owner) =
recoverOrderSigner(order, signingScheme, trade.signature);
recoveredOrder.uid.packOrderUidParams(
orderDigest,
owner,
order.validTo
);
recoveredOrder.owner = owner;
recoveredOrder.receiver = order.actualReceiver(owner);
}
/// @dev The length of any signature from an externally owned account.
uint256 private constant ECDSA_SIGNATURE_LENGTH = 65;
/// @dev Recovers an order's signer from the specified order and signature.
///
/// @param order The order to recover a signature for.
/// @param signingScheme The signing scheme.
/// @param signature The signature bytes.
/// @return orderDigest The computed order hash.
/// @return owner The recovered address from the specified signature.
function recoverOrderSigner(
GPv2Order.Data memory order,
Scheme signingScheme,
bytes calldata signature
) internal view returns (bytes32 orderDigest, address owner) {
orderDigest = order.hash(domainSeparator);
if (signingScheme == Scheme.Eip712) {
owner = recoverEip712Signer(orderDigest, signature);
} else if (signingScheme == Scheme.EthSign) {
owner = recoverEthsignSigner(orderDigest, signature);
} else if (signingScheme == Scheme.Eip1271) {
owner = recoverEip1271Signer(orderDigest, signature);
} else {
// signingScheme == Scheme.PreSign
owner = recoverPreSigner(orderDigest, signature, order.validTo);
}
}
/// @dev Perform an ECDSA recover for the specified message and calldata
/// signature.
///
/// The signature is encoded by tighyly packing the following struct:
/// ```
/// struct EncodedSignature {
/// bytes32 r;
/// bytes32 s;
/// uint8 v;
/// }
/// ```
///
/// @param message The signed message.
/// @param encodedSignature The encoded signature.
function ecdsaRecover(bytes32 message, bytes calldata encodedSignature)
internal
pure
returns (address signer)
{
require(
encodedSignature.length == ECDSA_SIGNATURE_LENGTH,
"GPv2: malformed ecdsa signature"
);
bytes32 r;
bytes32 s;
uint8 v;
// NOTE: Use assembly to efficiently decode signature data.
// solhint-disable-next-line no-inline-assembly
assembly {
// r = uint256(encodedSignature[0:32])
r := calldataload(encodedSignature.offset)
// s = uint256(encodedSignature[32:64])
s := calldataload(add(encodedSignature.offset, 32))
// v = uint8(encodedSignature[64])
v := shr(248, calldataload(add(encodedSignature.offset, 64)))
}
signer = ecrecover(message, v, r, s);
require(signer != address(0), "GPv2: invalid ecdsa signature");
}
/// @dev Decodes signature bytes originating from an EIP-712-encoded
/// signature.
///
/// EIP-712 signs typed data. The specifications are described in the
/// related EIP (<https://eips.ethereum.org/EIPS/eip-712>).
///
/// EIP-712 signatures are encoded as standard ECDSA signatures as described
/// in the corresponding decoding function [`ecdsaRecover`].
///
/// @param orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @param encodedSignature Calldata pointing to tightly packed signature
/// bytes.
/// @return owner The address of the signer.
function recoverEip712Signer(
bytes32 orderDigest,
bytes calldata encodedSignature
) internal pure returns (address owner) {
owner = ecdsaRecover(orderDigest, encodedSignature);
}
/// @dev Decodes signature bytes originating from the output of the eth_sign
/// RPC call.
///
/// The specifications are described in the Ethereum documentation
/// (<https://eth.wiki/json-rpc/API#eth_sign>).
///
/// eth_sign signatures are encoded as standard ECDSA signatures as
/// described in the corresponding decoding function
/// [`ecdsaRecover`].
///
/// @param orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @param encodedSignature Calldata pointing to tightly packed signature
/// bytes.
/// @return owner The address of the signer.
function recoverEthsignSigner(
bytes32 orderDigest,
bytes calldata encodedSignature
) internal pure returns (address owner) {
// The signed message is encoded as:
// `"\x19Ethereum Signed Message:\n" || length || data`, where
// the length is a constant (32 bytes) and the data is defined as:
// `orderDigest`.
bytes32 ethsignDigest =
keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
orderDigest
)
);
owner = ecdsaRecover(ethsignDigest, encodedSignature);
}
/// @dev Verifies the input calldata as an EIP-1271 contract signature and
/// returns the address of the signer.
///
/// The encoded signature tightly packs the following struct:
///
/// ```
/// struct EncodedEip1271Signature {
/// address owner;
/// bytes signature;
/// }
/// ```
///
/// This function enforces that the encoded data stores enough bytes to
/// cover the full length of the decoded signature.
///
/// @param encodedSignature The encoded EIP-1271 signature.
/// @param orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @return owner The address of the signer.
function recoverEip1271Signer(
bytes32 orderDigest,
bytes calldata encodedSignature
) internal view returns (address owner) {
// NOTE: Use assembly to read the verifier address from the encoded
// signature bytes.
// solhint-disable-next-line no-inline-assembly
assembly {
// owner = address(encodedSignature[0:20])
owner := shr(96, calldataload(encodedSignature.offset))
}
// NOTE: Configure prettier to ignore the following line as it causes
// a panic in the Solidity plugin.
// prettier-ignore
bytes calldata signature = encodedSignature[20:];
require(
EIP1271Verifier(owner).isValidSignature(orderDigest, signature) ==
GPv2EIP1271.MAGICVALUE,
"GPv2: invalid eip1271 signature"
);
}
/// @dev Verifies the order has been pre-signed. The signature is the
/// address of the signer of the order.
///
/// @param orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @param encodedSignature The pre-sign signature reprenting the order UID.
/// @param validTo The order expiry timestamp.
/// @return owner The address of the signer.
function recoverPreSigner(
bytes32 orderDigest,
bytes calldata encodedSignature,
uint32 validTo
) internal view returns (address owner) {
require(encodedSignature.length == 20, "GPv2: malformed presignature");
// NOTE: Use assembly to read the owner address from the encoded
// signature bytes.
// solhint-disable-next-line no-inline-assembly
assembly {
// owner = address(encodedSignature[0:20])
owner := shr(96, calldataload(encodedSignature.offset))
}
bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
orderUid.packOrderUidParams(orderDigest, owner, validTo);
require(
preSignature[orderUid] == PRE_SIGNED,
"GPv2: order not presigned"
);
}
}{
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract GPv2Authentication","name":"authenticator_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"Interaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"orderUid","type":"bytes"}],"name":"OrderInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes","name":"orderUid","type":"bytes"},{"indexed":false,"internalType":"bool","name":"signed","type":"bool"}],"name":"PreSignature","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"solver","type":"address"}],"name":"Settlement","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"contract IERC20","name":"sellToken","type":"address"},{"indexed":false,"internalType":"contract IERC20","name":"buyToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"sellAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"orderUid","type":"bytes"}],"name":"Trade","type":"event"},{"inputs":[],"name":"allowanceManager","outputs":[{"internalType":"contract GPv2AllowanceManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authenticator","outputs":[{"internalType":"contract GPv2Authentication","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"filledAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"orderUids","type":"bytes[]"}],"name":"freeFilledAmountStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"orderUids","type":"bytes[]"}],"name":"freePreSignatureStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"getStorageAt","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"orderUid","type":"bytes"}],"name":"invalidateOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"preSignature","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"orderUid","type":"bytes"},{"internalType":"bool","name":"signed","type":"bool"}],"name":"setPreSignature","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"clearingPrices","type":"uint256[]"},{"components":[{"internalType":"uint256","name":"sellTokenIndex","type":"uint256"},{"internalType":"uint256","name":"buyTokenIndex","type":"uint256"},{"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":"uint256","name":"flags","type":"uint256"},{"internalType":"uint256","name":"executedAmount","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct GPv2Trade.Data[]","name":"trades","type":"tuple[]"},{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"internalType":"struct GPv2Interaction.Data[][3]","name":"interactions","type":"tuple[][3]"}],"name":"settle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"targetContract","type":"address"},{"internalType":"bytes","name":"calldataPayload","type":"bytes"}],"name":"simulateDelegatecall","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"targetContract","type":"address"},{"internalType":"bytes","name":"calldataPayload","type":"bytes"}],"name":"simulateDelegatecallInternal","outputs":[{"internalType":"bytes","name":"response","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60e06040523480156200001157600080fd5b50604051620031b9380380620031b9833981016040819052620000349162000146565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f6c85c0337eba1661327f94f3bf46c8a7f9311a563f4d5c948362567f5d8ed60c828401527ff9446b8e937d86f0bc87cac73923491692b123ca5f8761908494703758206adf606080840191909152466080808501919091523060a08086019190915285518086038201815260c09095019586905284519490930193909320909252600180559083901b6001600160601b0319169052620001039062000138565b604051809103906000f08015801562000120573d6000803e3d6000fd5b5060601b6001600160601b03191660c0525062000176565b6104558062002d6483390190565b60006020828403121562000158578081fd5b81516001600160a01b03811681146200016f578182fd5b9392505050565b60805160a05160601c60c05160601c612ba7620001bd6000398061047752806108ae5280610da15250806103475280610636525080610af352806117435250612ba76000f3fe6080604052600436106100d65760003560e01c8063a2a7d51b1161007f578063ec6cb13f11610059578063ec6cb13f1461021e578063ed9f35ce1461023e578063f698da251461025e578063f84436bd14610273576100dd565b8063a2a7d51b146101c9578063c4b1e4fb146101e9578063d08d33d1146101fe576100dd565b80632479fb6e116100b05780632479fb6e1461014f57806343218e191461017c5780635624b25b146101a9576100dd565b806313d79a0b146100e257806315337bc0146101045780632335c76b14610124576100dd565b366100dd57005b600080fd5b3480156100ee57600080fd5b506101026100fd366004612432565b610293565b005b34801561011057600080fd5b5061010261011f36600461250d565b61053b565b34801561013057600080fd5b50610139610634565b6040516101469190612660565b60405180910390f35b34801561015b57600080fd5b5061016f61016a366004612596565b610658565b6040516101469190612718565b34801561018857600080fd5b5061019c6101973660046123a6565b610675565b604051610146919061276e565b3480156101b557600080fd5b5061019c6101c43660046125c9565b6107ed565b3480156101d557600080fd5b506101026101e43660046123f2565b610863565b3480156101f557600080fd5b506101396108ac565b34801561020a57600080fd5b5061016f610219366004612596565b6108d0565b34801561022a57600080fd5b50610102610239366004612541565b6108ed565b34801561024a57600080fd5b506101026102593660046123f2565b610aac565b34801561026a57600080fd5b5061016f610af1565b34801561027f57600080fd5b5061019c61028e3660046123a6565b610b15565b6002600154141561030557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026001556040517f02cc250d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906302cc250d9061037c903390600401612660565b60206040518083038186803b15801561039457600080fd5b505afa1580156103a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cc91906124f1565b61040b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612922565b60405180910390fd5b6104278160005b60200281019061042291906129c0565b610d5e565b6000610437888888888888610e9b565b6040517faef733d700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063aef733d7906104ac908490600401612681565b600060405180830381600087803b1580156104c657600080fd5b505af11580156104da573d6000803e3d6000fd5b505050506104ee8260016003811061041257fe5b6104f781610f98565b610502826002610412565b60405133907f40338ce1a7c49204f0099533b1e9a7ee0a3d261f84974ab7af36105b8c4e9db490600090a2505060018055505050505050565b60006105478383610fc8565b5091505073ffffffffffffffffffffffffffffffffffffffff8116331461059a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906127d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600284846040516105cd929190612634565b9081526020016040518091039020819055508073ffffffffffffffffffffffffffffffffffffffff167f875b6cb035bbd4ac6500fabc6d1e4ca5bdc58a3e2b424ccb5c24cdbebeb009a98484604051610627929190612721565b60405180910390a2505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b805160208183018101805160028252928201919093012091525481565b606060008373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106106de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106a1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b5080935081925050506107e682826040516020018083805190602001908083835b602083106107a157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610764565b6001836020036101000a03801982511681845116808217855250505050505090500182151560f81b815260010192505050604051602081830303815290604052611056565b5092915050565b606060008260200267ffffffffffffffff8111801561080b57600080fd5b506040519080825280601f01601f191660200182016040528015610836576020820181803683370190505b50905060005b83811015610859578481015460208083028401015260010161083c565b5090505b92915050565b30331461089c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061287d565b6108a86000838361105e565b5050565b7f000000000000000000000000000000000000000000000000000000000000000081565b805160208183018101805160008252928201919093012091525481565b60006108f98484610fc8565b5091505073ffffffffffffffffffffffffffffffffffffffff8116331461098157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f475076323a2063616e6e6f74207072657369676e206f72646572000000000000604482015290519081900360640190fd5b81156109db577ff59c009283ff87aa78203fc4d9c2df025ee851130fb69cc3e068941f6b5e2d6f60001c60008585604051808383808284378083019250505092505050908152602001604051809103902081905550610a07565b600080858560405180838380828437919091019485525050604051928390036020019092209290925550505b8073ffffffffffffffffffffffffffffffffffffffff167f01bf7c8b0ca55deecbea89d7e58295b7ffbf685fd0d96801034ba8c6ffe1c68d858585604051808060200183151581526020018281038252858582818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201829003965090945050505050a250505050565b303314610ae5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061287d565b6108a86002838361105e565b7f000000000000000000000000000000000000000000000000000000000000000081565b606060006343218e1960e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610b7f578181015183820152602001610b67565b50505050905090810190601f168015610bac5780820380516001836020036101000a031916815260200191505b50604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909816979097178752518151919750309688965090945084935091508083835b60208310610c7d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c40565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610cdf576040519150601f19603f3d011682016040523d82523d6000602084013e610ce4565b606091505b50905080925050600082600184510381518110610cfd57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600160f81b149050610d40836001855103611114565b8015610d4d57505061085d565b610d5683611056565b505092915050565b60005b81811015610e965736838383818110610d7657fe5b9050602002810190610d889190612a88565b905073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016610dce602083018361238c565b73ffffffffffffffffffffffffffffffffffffffff161415610e1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612959565b610e2581611118565b610e32602082018261238c565b73ffffffffffffffffffffffffffffffffffffffff167fed99827efb37016f2275f98c4bcf71c7551c75d59e9b450f79fa32e60be672c28260200135610e778461116f565b604051610e85929190612990565b60405180910390a250600101610d61565b505050565b60606000610ea7611199565b90508267ffffffffffffffff81118015610ec057600080fd5b50604051908082528060200260200182016040528015610efa57816020015b610ee7612191565b815260200190600190039081610edf5790505b50915060005b83811015610f8c5736858583818110610f1557fe5b9050602002810190610f279190612abb565b9050610f35838b8b846111c6565b610f838389898435818110610f4657fe5b905060200201358a8a8560200135818110610f5d57fe5b90506020020135846101200135888781518110610f7657fe5b6020026020010151611264565b50600101610f00565b50509695505050505050565b60005b81518110156108a857610fc0828281518110610fb357fe5b60200260200101516115a0565b600101610f9b565b600080806038841461103b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f475076323a20696e76616c696420756964000000000000000000000000000000604482015290519081900360640190fd5b5050823593602084013560601c936034013560e01c92509050565b805160208201fd5b60005b8181101561110e5736600084848481811061107857fe5b905060200281019061108a9190612a25565b91509150600061109a8383610fc8565b92505050428163ffffffff16106110dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128eb565b60008784846040516110f0929190612634565b90815260405190819003602001902055505060019091019050611061565b50505050565b9052565b73ffffffffffffffffffffffffffffffffffffffff81351660208201353660006111456040860186612a25565b9150915060405181838237600080838387895af1611167573d6000803e3d6000fd5b505050505050565b600036816111806040850185612a25565b90925090506004811061119257813592505b5050919050565b6111a16121c6565b6040805160388082526060820190925290602082018180368337505050602082015290565b835160006111d683868685611664565b90506000806111f384846111ee610140890189612a25565b61173a565b9150915061121682828660a001518b602001516117e9909392919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff8116604089015261123c848261186b565b73ffffffffffffffffffffffffffffffffffffffff1660609098019790975250505050505050565b8451602086015160a08201514263ffffffff90911610156112b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061280f565b60408088015173ffffffffffffffffffffffffffffffffffffffff90811685526060808a0151821660208088019190915285518316938701939093529184015116908401526080820151611305908661189d565b6060830151611314908861189d565b101561134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612846565b6000806000807ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775866101000151141561144357856101200151156113b057606086015160e08701518995506113a1908661189d565b816113a857fe5b0491506113bf565b856060015193508560e0015191505b886113ca858c61189d565b816113d157fe5b0492506113fe846002876040516113e89190612644565b9081526040519081900360200190205490611917565b9050856060015181111561143e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128b4565b6114ec565b8561012001511561147457608086015160e0870151899450611465908561189d565b8161146c57fe5b049150611483565b856080015192508560e0015191505b8961148e848b61189d565b8161149557fe5b0493506114ac836002876040516113e89190612644565b905085608001518111156114ec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128b4565b6114f68483611917565b608088015260a087018390526040518190600290611515908890612644565b908152602001604051809103902081905550866000015173ffffffffffffffffffffffffffffffffffffffff167fa07a543ab8a018198e99ca0184c93fe9050a79400a0a723441f84de1d972cc17886040015189606001518a608001518b60a00151878b60405161158b96959493929190612781565b60405180910390a25050505050505050505050565b606081015173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561162a57806020015173ffffffffffffffffffffffffffffffffffffffff166108fc8260a001519081150290604051600060405180830381858888f19350505050158015611624573d6000803e3d6000fd5b50611661565b61166181602001518260a00151836060015173ffffffffffffffffffffffffffffffffffffffff1661198b9092919063ffffffff16565b50565b60008383863581811061167357fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff16845250849084908701358181106116a657fe5b73ffffffffffffffffffffffffffffffffffffffff602091820293909301358316908501525060408087013590911690830152606080860135908301526080808601359083015263ffffffff60a080870135919091169083015260c0808601359083015260e08086013590830152611722610100860135611a62565b90151561012085015261010090930152509392505050565b600080611767867f0000000000000000000000000000000000000000000000000000000000000000611ad9565b9150600085600381111561177757fe5b141561178f57611788828585611b63565b90506117e0565b600185600381111561179d57fe5b14156117ae57611788828585611b78565b60028560038111156117bc57fe5b14156117cd57611788828585611be0565b6117dd8285858960a00151611d7e565b90505b94509492505050565b603884511461185957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a2075696420627566666572206f766572666c6f7700000000000000604482015290519081900360640190fd5b60388401526034830152602090910152565b604082015160009073ffffffffffffffffffffffffffffffffffffffff1661189457508061085d565b50506040015190565b6000826118ac5750600061085d565b828202828482816118b957fe5b0414611910576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180612b516021913960400191505060405180910390fd5b9392505050565b60008282018381101561191057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff84166004830152602482018390529060008060448382895af16119ee573d6000803e3d6000fd5b506119f7611f43565b61110e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f475076323a206661696c6564207472616e736665720000000000000000000000604482015290519081900360640190fd5b6000808060018416611a96577ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee3467759250611aba565b7f6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc92505b60028085161515925084901c6003811115611ad157fe5b929491935050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090910180517fd604be04a8c6d2df582ec82eba9b65ce714008acbf9122dd95e499569c8f1a808252610160822091526040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6000611b70848484611fe6565b949350505050565b6000808460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c01828152602001915050604051602081830303815290604052805190602001209050611bd7818585611fe6565b95945050505050565b813560601c366000611bf58460148188612aee565b604080517f1626ba7e00000000000000000000000000000000000000000000000000000000808252600482018b81526024830193845260448301859052949650929450919273ffffffffffffffffffffffffffffffffffffffff871692631626ba7e928b928892889290606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015611cbb57600080fd5b505afa158015611ccf573d6000803e3d6000fd5b505050506040513d6020811015611ce557600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614611d7557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a20696e76616c69642065697031323731207369676e617475726500604482015290519081900360640190fd5b50509392505050565b600060148314611def57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f475076323a206d616c666f726d6564207072657369676e617475726500000000604482015290519081900360640190fd5b506040805160388082526060828101909352853590921c9160009190602082018180368337019050509050611e26818784866117e9565b7ff59c009283ff87aa78203fc4d9c2df025ee851130fb69cc3e068941f6b5e2d6f60001c6000826040518082805190602001908083835b60208310611e9a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611e5d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205414611f3a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206f72646572206e6f74207072657369676e656400000000000000604482015290519081900360640190fd5b50949350505050565b6000803d8015611f5e5760208114611f675760019150611f74565b60019250611f74565b3d6000803e600051151592505b508015611fe257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a206d616c666f726d6564207472616e7366657220726573756c7400604482015290519081900360640190fd5b5090565b60006041821461205757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a206d616c666f726d6564206563647361207369676e617475726500604482015290519081900360640190fd5b604080516000815260208181018084528790528286013560f81c82840181905286356060840181905282880135608085018190529451909493919260019260a0808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa1580156120da573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015194505073ffffffffffffffffffffffffffffffffffffffff841661218757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f475076323a20696e76616c6964206563647361207369676e6174757265000000604482015290519081900360640190fd5b5050509392505050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60405180608001604052806121d96121f3565b815260606020820181905260006040830181905291015290565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803573ffffffffffffffffffffffffffffffffffffffff8116811461226b57600080fd5b919050565b60008083601f840112612281578182fd5b50813567ffffffffffffffff811115612298578182fd5b60208301915083602080830285010111156122b257600080fd5b9250929050565b60008083601f8401126122ca578182fd5b50813567ffffffffffffffff8111156122e1578182fd5b6020830191508360208285010111156122b257600080fd5b600082601f830112612309578081fd5b813567ffffffffffffffff8082111561231e57fe5b60405160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116820101818110838211171561235a57fe5b604052828152848301602001861015612371578384fd5b82602086016020830137918201602001929092529392505050565b60006020828403121561239d578081fd5b61191082612247565b600080604083850312156123b8578081fd5b6123c183612247565b9150602083013567ffffffffffffffff8111156123dc578182fd5b6123e8858286016122f9565b9150509250929050565b60008060208385031215612404578182fd5b823567ffffffffffffffff81111561241a578283fd5b61242685828601612270565b90969095509350505050565b60008060008060008060006080888a03121561244c578283fd5b873567ffffffffffffffff80821115612463578485fd5b61246f8b838c01612270565b909950975060208a0135915080821115612487578485fd5b6124938b838c01612270565b909750955060408a01359150808211156124ab578485fd5b6124b78b838c01612270565b909550935060608a01359150808211156124cf578283fd5b508801606081018a10156124e1578182fd5b8091505092959891949750929550565b600060208284031215612502578081fd5b815161191081612b42565b6000806020838503121561251f578182fd5b823567ffffffffffffffff811115612535578283fd5b612426858286016122b9565b600080600060408486031215612555578283fd5b833567ffffffffffffffff81111561256b578384fd5b612577868287016122b9565b909450925050602084013561258b81612b42565b809150509250925092565b6000602082840312156125a7578081fd5b813567ffffffffffffffff8111156125bd578182fd5b611b70848285016122f9565b600080604083850312156125db578182fd5b50508035926020909101359150565b60008151808452612602816020860160208601612b16565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b60008251612656818460208701612b16565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b602080825282518282018190526000919060409081850190868401855b8281101561270b578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015181168887015286820151811687870152606080830151909116908601526080808201519086015260a0908101519085015260c0909301929085019060010161269e565b5091979650505050505050565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020825261191060208301846125ea565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015283608083015260c060a08301526127cc60c08301846125ea565b98975050505050505050565b6020808252601f908201527f475076323a2063616c6c657220646f6573206e6f74206f776e206f7264657200604082015260600190565b60208082526013908201527f475076323a206f72646572206578706972656400000000000000000000000000604082015260600190565b6020808252601f908201527f475076323a206c696d6974207072696365206e6f742072657370656374656400604082015260600190565b60208082526018908201527f475076323a206e6f7420616e20696e746572616374696f6e0000000000000000604082015260600190565b60208082526012908201527f475076323a206f726465722066696c6c65640000000000000000000000000000604082015260600190565b60208082526017908201527f475076323a206f72646572207374696c6c2076616c6964000000000000000000604082015260600190565b60208082526012908201527f475076323a206e6f74206120736f6c7665720000000000000000000000000000604082015260600190565b6020808252601b908201527f475076323a20666f7262696464656e20696e746572616374696f6e0000000000604082015260600190565b9182527fffffffff0000000000000000000000000000000000000000000000000000000016602082015260400190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126129f4578283fd5b83018035915067ffffffffffffffff821115612a0e578283fd5b60209081019250810236038213156122b257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a59578182fd5b83018035915067ffffffffffffffff821115612a73578283fd5b6020019150368190038213156122b257600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112612656578182fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1833603018112612656578182fd5b60008085851115612afd578182fd5b83861115612b09578182fd5b5050820193919092039150565b60005b83811015612b31578181015183820152602001612b19565b8381111561110e5750506000910152565b801515811461166157600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122040a5ddd344864831a3f7821307d47d6689b5d924f16a460299288e0a65d399b864736f6c6343000706003360a060405234801561001057600080fd5b5033606081901b60805261042561003060003980605d52506104256000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063aef733d714610030575b600080fd5b61004361003e366004610348565b610045565b005b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146100bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100b4906103b8565b60405180910390fd5b60005b818110156100eb576100e38383838181106100d757fe5b905060c00201336100f0565b6001016100c0565b505050565b604082013573ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561018d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f475076323a2063616e6e6f74207472616e73666572206e617469766520455448604482015290519081900360640190fd5b6101bb73ffffffffffffffffffffffffffffffffffffffff60408401358116908435168360808601356101bf565b5050565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff8581166004840152841660248301526044820183905290600080606483828a5af161022a573d6000803e3d6000fd5b506102336102a5565b61029e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206661696c6564207472616e7366657246726f6d00000000000000604482015290519081900360640190fd5b5050505050565b6000803d80156102c057602081146102c957600191506102d6565b600192506102d6565b3d6000803e600051151592505b50801561034457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a206d616c666f726d6564207472616e7366657220726573756c7400604482015290519081900360640190fd5b5090565b6000806020838503121561035a578182fd5b823567ffffffffffffffff80821115610371578384fd5b818501915085601f830112610384578384fd5b813581811115610392578485fd5b86602060c0830285010111156103a6578485fd5b60209290920196919550909350505050565b6020808252601d908201527f475076323a206e6f7420616c6c6f77616e636520726563697069656e7400000060408201526060019056fea2646970667358221220149613821ec7e26c7ca23bb4d44976eaba202d71fbaa8b8f222beab055627c3b64736f6c63430007060033000000000000000000000000bbfb9a525acdd2ab3a5eb5fc9ab8cf53b881000e
Deployed Bytecode
0x6080604052600436106100d65760003560e01c8063a2a7d51b1161007f578063ec6cb13f11610059578063ec6cb13f1461021e578063ed9f35ce1461023e578063f698da251461025e578063f84436bd14610273576100dd565b8063a2a7d51b146101c9578063c4b1e4fb146101e9578063d08d33d1146101fe576100dd565b80632479fb6e116100b05780632479fb6e1461014f57806343218e191461017c5780635624b25b146101a9576100dd565b806313d79a0b146100e257806315337bc0146101045780632335c76b14610124576100dd565b366100dd57005b600080fd5b3480156100ee57600080fd5b506101026100fd366004612432565b610293565b005b34801561011057600080fd5b5061010261011f36600461250d565b61053b565b34801561013057600080fd5b50610139610634565b6040516101469190612660565b60405180910390f35b34801561015b57600080fd5b5061016f61016a366004612596565b610658565b6040516101469190612718565b34801561018857600080fd5b5061019c6101973660046123a6565b610675565b604051610146919061276e565b3480156101b557600080fd5b5061019c6101c43660046125c9565b6107ed565b3480156101d557600080fd5b506101026101e43660046123f2565b610863565b3480156101f557600080fd5b506101396108ac565b34801561020a57600080fd5b5061016f610219366004612596565b6108d0565b34801561022a57600080fd5b50610102610239366004612541565b6108ed565b34801561024a57600080fd5b506101026102593660046123f2565b610aac565b34801561026a57600080fd5b5061016f610af1565b34801561027f57600080fd5b5061019c61028e3660046123a6565b610b15565b6002600154141561030557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b60026001556040517f02cc250d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bbfb9a525acdd2ab3a5eb5fc9ab8cf53b881000e16906302cc250d9061037c903390600401612660565b60206040518083038186803b15801561039457600080fd5b505afa1580156103a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cc91906124f1565b61040b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612922565b60405180910390fd5b6104278160005b60200281019061042291906129c0565b610d5e565b6000610437888888888888610e9b565b6040517faef733d700000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d8e28184408bc4790e79fd08ed67f7ebacbebcc169063aef733d7906104ac908490600401612681565b600060405180830381600087803b1580156104c657600080fd5b505af11580156104da573d6000803e3d6000fd5b505050506104ee8260016003811061041257fe5b6104f781610f98565b610502826002610412565b60405133907f40338ce1a7c49204f0099533b1e9a7ee0a3d261f84974ab7af36105b8c4e9db490600090a2505060018055505050505050565b60006105478383610fc8565b5091505073ffffffffffffffffffffffffffffffffffffffff8116331461059a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906127d8565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600284846040516105cd929190612634565b9081526020016040518091039020819055508073ffffffffffffffffffffffffffffffffffffffff167f875b6cb035bbd4ac6500fabc6d1e4ca5bdc58a3e2b424ccb5c24cdbebeb009a98484604051610627929190612721565b60405180910390a2505050565b7f000000000000000000000000bbfb9a525acdd2ab3a5eb5fc9ab8cf53b881000e81565b805160208183018101805160028252928201919093012091525481565b606060008373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083106106de57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016106a1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461073e576040519150601f19603f3d011682016040523d82523d6000602084013e610743565b606091505b5080935081925050506107e682826040516020018083805190602001908083835b602083106107a157805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610764565b6001836020036101000a03801982511681845116808217855250505050505090500182151560f81b815260010192505050604051602081830303815290604052611056565b5092915050565b606060008260200267ffffffffffffffff8111801561080b57600080fd5b506040519080825280601f01601f191660200182016040528015610836576020820181803683370190505b50905060005b83811015610859578481015460208083028401015260010161083c565b5090505b92915050565b30331461089c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061287d565b6108a86000838361105e565b5050565b7f0000000000000000000000007d8e28184408bc4790e79fd08ed67f7ebacbebcc81565b805160208183018101805160008252928201919093012091525481565b60006108f98484610fc8565b5091505073ffffffffffffffffffffffffffffffffffffffff8116331461098157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f475076323a2063616e6e6f74207072657369676e206f72646572000000000000604482015290519081900360640190fd5b81156109db577ff59c009283ff87aa78203fc4d9c2df025ee851130fb69cc3e068941f6b5e2d6f60001c60008585604051808383808284378083019250505092505050908152602001604051809103902081905550610a07565b600080858560405180838380828437919091019485525050604051928390036020019092209290925550505b8073ffffffffffffffffffffffffffffffffffffffff167f01bf7c8b0ca55deecbea89d7e58295b7ffbf685fd0d96801034ba8c6ffe1c68d858585604051808060200183151581526020018281038252858582818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201829003965090945050505050a250505050565b303314610ae5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061287d565b6108a86002838361105e565b7f301b1798966c86b41fd8236f0fd639809ea3ce213a5acd2ea7c456566ca34ead81565b606060006343218e1960e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610b7f578181015183820152602001610b67565b50505050905090810190601f168015610bac5780820380516001836020036101000a031916815260200191505b50604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909816979097178752518151919750309688965090945084935091508083835b60208310610c7d57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c40565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610cdf576040519150601f19603f3d011682016040523d82523d6000602084013e610ce4565b606091505b50905080925050600082600184510381518110610cfd57fe5b602001015160f81c60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916600160f81b149050610d40836001855103611114565b8015610d4d57505061085d565b610d5683611056565b505092915050565b60005b81811015610e965736838383818110610d7657fe5b9050602002810190610d889190612a88565b905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000007d8e28184408bc4790e79fd08ed67f7ebacbebcc16610dce602083018361238c565b73ffffffffffffffffffffffffffffffffffffffff161415610e1c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612959565b610e2581611118565b610e32602082018261238c565b73ffffffffffffffffffffffffffffffffffffffff167fed99827efb37016f2275f98c4bcf71c7551c75d59e9b450f79fa32e60be672c28260200135610e778461116f565b604051610e85929190612990565b60405180910390a250600101610d61565b505050565b60606000610ea7611199565b90508267ffffffffffffffff81118015610ec057600080fd5b50604051908082528060200260200182016040528015610efa57816020015b610ee7612191565b815260200190600190039081610edf5790505b50915060005b83811015610f8c5736858583818110610f1557fe5b9050602002810190610f279190612abb565b9050610f35838b8b846111c6565b610f838389898435818110610f4657fe5b905060200201358a8a8560200135818110610f5d57fe5b90506020020135846101200135888781518110610f7657fe5b6020026020010151611264565b50600101610f00565b50509695505050505050565b60005b81518110156108a857610fc0828281518110610fb357fe5b60200260200101516115a0565b600101610f9b565b600080806038841461103b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f475076323a20696e76616c696420756964000000000000000000000000000000604482015290519081900360640190fd5b5050823593602084013560601c936034013560e01c92509050565b805160208201fd5b60005b8181101561110e5736600084848481811061107857fe5b905060200281019061108a9190612a25565b91509150600061109a8383610fc8565b92505050428163ffffffff16106110dd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128eb565b60008784846040516110f0929190612634565b90815260405190819003602001902055505060019091019050611061565b50505050565b9052565b73ffffffffffffffffffffffffffffffffffffffff81351660208201353660006111456040860186612a25565b9150915060405181838237600080838387895af1611167573d6000803e3d6000fd5b505050505050565b600036816111806040850185612a25565b90925090506004811061119257813592505b5050919050565b6111a16121c6565b6040805160388082526060820190925290602082018180368337505050602082015290565b835160006111d683868685611664565b90506000806111f384846111ee610140890189612a25565b61173a565b9150915061121682828660a001518b602001516117e9909392919063ffffffff16565b73ffffffffffffffffffffffffffffffffffffffff8116604089015261123c848261186b565b73ffffffffffffffffffffffffffffffffffffffff1660609098019790975250505050505050565b8451602086015160a08201514263ffffffff90911610156112b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104029061280f565b60408088015173ffffffffffffffffffffffffffffffffffffffff90811685526060808a0151821660208088019190915285518316938701939093529184015116908401526080820151611305908661189d565b6060830151611314908861189d565b101561134c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040290612846565b6000806000807ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775866101000151141561144357856101200151156113b057606086015160e08701518995506113a1908661189d565b816113a857fe5b0491506113bf565b856060015193508560e0015191505b886113ca858c61189d565b816113d157fe5b0492506113fe846002876040516113e89190612644565b9081526040519081900360200190205490611917565b9050856060015181111561143e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128b4565b6114ec565b8561012001511561147457608086015160e0870151899450611465908561189d565b8161146c57fe5b049150611483565b856080015192508560e0015191505b8961148e848b61189d565b8161149557fe5b0493506114ac836002876040516113e89190612644565b905085608001518111156114ec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610402906128b4565b6114f68483611917565b608088015260a087018390526040518190600290611515908890612644565b908152602001604051809103902081905550866000015173ffffffffffffffffffffffffffffffffffffffff167fa07a543ab8a018198e99ca0184c93fe9050a79400a0a723441f84de1d972cc17886040015189606001518a608001518b60a00151878b60405161158b96959493929190612781565b60405180910390a25050505050505050505050565b606081015173ffffffffffffffffffffffffffffffffffffffff1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561162a57806020015173ffffffffffffffffffffffffffffffffffffffff166108fc8260a001519081150290604051600060405180830381858888f19350505050158015611624573d6000803e3d6000fd5b50611661565b61166181602001518260a00151836060015173ffffffffffffffffffffffffffffffffffffffff1661198b9092919063ffffffff16565b50565b60008383863581811061167357fe5b6020908102929092013573ffffffffffffffffffffffffffffffffffffffff16845250849084908701358181106116a657fe5b73ffffffffffffffffffffffffffffffffffffffff602091820293909301358316908501525060408087013590911690830152606080860135908301526080808601359083015263ffffffff60a080870135919091169083015260c0808601359083015260e08086013590830152611722610100860135611a62565b90151561012085015261010090930152509392505050565b600080611767867f301b1798966c86b41fd8236f0fd639809ea3ce213a5acd2ea7c456566ca34ead611ad9565b9150600085600381111561177757fe5b141561178f57611788828585611b63565b90506117e0565b600185600381111561179d57fe5b14156117ae57611788828585611b78565b60028560038111156117bc57fe5b14156117cd57611788828585611be0565b6117dd8285858960a00151611d7e565b90505b94509492505050565b603884511461185957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a2075696420627566666572206f766572666c6f7700000000000000604482015290519081900360640190fd5b60388401526034830152602090910152565b604082015160009073ffffffffffffffffffffffffffffffffffffffff1661189457508061085d565b50506040015190565b6000826118ac5750600061085d565b828202828482816118b957fe5b0414611910576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180612b516021913960400191505060405180910390fd5b9392505050565b60008282018381101561191057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000080825273ffffffffffffffffffffffffffffffffffffffff84166004830152602482018390529060008060448382895af16119ee573d6000803e3d6000fd5b506119f7611f43565b61110e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f475076323a206661696c6564207472616e736665720000000000000000000000604482015290519081900360640190fd5b6000808060018416611a96577ff3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee3467759250611aba565b7f6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc92505b60028085161515925084901c6003811115611ad157fe5b929491935050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090910180517fd604be04a8c6d2df582ec82eba9b65ce714008acbf9122dd95e499569c8f1a808252610160822091526040517f19010000000000000000000000000000000000000000000000000000000000008152600281019290925260228201526042902090565b6000611b70848484611fe6565b949350505050565b6000808460405160200180807f19457468657265756d205369676e6564204d6573736167653a0a333200000000815250601c01828152602001915050604051602081830303815290604052805190602001209050611bd7818585611fe6565b95945050505050565b813560601c366000611bf58460148188612aee565b604080517f1626ba7e00000000000000000000000000000000000000000000000000000000808252600482018b81526024830193845260448301859052949650929450919273ffffffffffffffffffffffffffffffffffffffff871692631626ba7e928b928892889290606401848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016909201965060209550909350505081840390508186803b158015611cbb57600080fd5b505afa158015611ccf573d6000803e3d6000fd5b505050506040513d6020811015611ce557600080fd5b50517fffffffff000000000000000000000000000000000000000000000000000000001614611d7557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a20696e76616c69642065697031323731207369676e617475726500604482015290519081900360640190fd5b50509392505050565b600060148314611def57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f475076323a206d616c666f726d6564207072657369676e617475726500000000604482015290519081900360640190fd5b506040805160388082526060828101909352853590921c9160009190602082018180368337019050509050611e26818784866117e9565b7ff59c009283ff87aa78203fc4d9c2df025ee851130fb69cc3e068941f6b5e2d6f60001c6000826040518082805190602001908083835b60208310611e9a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611e5d565b6001836020036101000a03801982511681845116808217855250505050505090500191505090815260200160405180910390205414611f3a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f475076323a206f72646572206e6f74207072657369676e656400000000000000604482015290519081900360640190fd5b50949350505050565b6000803d8015611f5e5760208114611f675760019150611f74565b60019250611f74565b3d6000803e600051151592505b508015611fe257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a206d616c666f726d6564207472616e7366657220726573756c7400604482015290519081900360640190fd5b5090565b60006041821461205757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f475076323a206d616c666f726d6564206563647361207369676e617475726500604482015290519081900360640190fd5b604080516000815260208181018084528790528286013560f81c82840181905286356060840181905282880135608085018190529451909493919260019260a0808201937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081019281900390910190855afa1580156120da573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015194505073ffffffffffffffffffffffffffffffffffffffff841661218757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f475076323a20696e76616c6964206563647361207369676e6174757265000000604482015290519081900360640190fd5b5050509392505050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60405180608001604052806121d96121f3565b815260606020820181905260006040830181905291015290565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803573ffffffffffffffffffffffffffffffffffffffff8116811461226b57600080fd5b919050565b60008083601f840112612281578182fd5b50813567ffffffffffffffff811115612298578182fd5b60208301915083602080830285010111156122b257600080fd5b9250929050565b60008083601f8401126122ca578182fd5b50813567ffffffffffffffff8111156122e1578182fd5b6020830191508360208285010111156122b257600080fd5b600082601f830112612309578081fd5b813567ffffffffffffffff8082111561231e57fe5b60405160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f850116820101818110838211171561235a57fe5b604052828152848301602001861015612371578384fd5b82602086016020830137918201602001929092529392505050565b60006020828403121561239d578081fd5b61191082612247565b600080604083850312156123b8578081fd5b6123c183612247565b9150602083013567ffffffffffffffff8111156123dc578182fd5b6123e8858286016122f9565b9150509250929050565b60008060208385031215612404578182fd5b823567ffffffffffffffff81111561241a578283fd5b61242685828601612270565b90969095509350505050565b60008060008060008060006080888a03121561244c578283fd5b873567ffffffffffffffff80821115612463578485fd5b61246f8b838c01612270565b909950975060208a0135915080821115612487578485fd5b6124938b838c01612270565b909750955060408a01359150808211156124ab578485fd5b6124b78b838c01612270565b909550935060608a01359150808211156124cf578283fd5b508801606081018a10156124e1578182fd5b8091505092959891949750929550565b600060208284031215612502578081fd5b815161191081612b42565b6000806020838503121561251f578182fd5b823567ffffffffffffffff811115612535578283fd5b612426858286016122b9565b600080600060408486031215612555578283fd5b833567ffffffffffffffff81111561256b578384fd5b612577868287016122b9565b909450925050602084013561258b81612b42565b809150509250925092565b6000602082840312156125a7578081fd5b813567ffffffffffffffff8111156125bd578182fd5b611b70848285016122f9565b600080604083850312156125db578182fd5b50508035926020909101359150565b60008151808452612602816020860160208601612b16565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6000828483379101908152919050565b60008251612656818460208701612b16565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b602080825282518282018190526000919060409081850190868401855b8281101561270b578151805173ffffffffffffffffffffffffffffffffffffffff90811686528782015181168887015286820151811687870152606080830151909116908601526080808201519086015260a0908101519085015260c0909301929085019060010161269e565b5091979650505050505050565b90815260200190565b60006020825282602083015282846040840137818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020825261191060208301846125ea565b600073ffffffffffffffffffffffffffffffffffffffff808916835280881660208401525085604083015284606083015283608083015260c060a08301526127cc60c08301846125ea565b98975050505050505050565b6020808252601f908201527f475076323a2063616c6c657220646f6573206e6f74206f776e206f7264657200604082015260600190565b60208082526013908201527f475076323a206f72646572206578706972656400000000000000000000000000604082015260600190565b6020808252601f908201527f475076323a206c696d6974207072696365206e6f742072657370656374656400604082015260600190565b60208082526018908201527f475076323a206e6f7420616e20696e746572616374696f6e0000000000000000604082015260600190565b60208082526012908201527f475076323a206f726465722066696c6c65640000000000000000000000000000604082015260600190565b60208082526017908201527f475076323a206f72646572207374696c6c2076616c6964000000000000000000604082015260600190565b60208082526012908201527f475076323a206e6f74206120736f6c7665720000000000000000000000000000604082015260600190565b6020808252601b908201527f475076323a20666f7262696464656e20696e746572616374696f6e0000000000604082015260600190565b9182527fffffffff0000000000000000000000000000000000000000000000000000000016602082015260400190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126129f4578283fd5b83018035915067ffffffffffffffff821115612a0e578283fd5b60209081019250810236038213156122b257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a59578182fd5b83018035915067ffffffffffffffff821115612a73578283fd5b6020019150368190038213156122b257600080fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa1833603018112612656578182fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1833603018112612656578182fd5b60008085851115612afd578182fd5b83861115612b09578182fd5b5050820193919092039150565b60005b83811015612b31578181015183820152602001612b19565b8381111561110e5750506000910152565b801515811461166157600080fdfe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a264697066735822122040a5ddd344864831a3f7821307d47d6689b5d924f16a460299288e0a65d399b864736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000bbfb9a525acdd2ab3a5eb5fc9ab8cf53b881000e
-----Decoded View---------------
Arg [0] : authenticator_ (address): 0xbbfB9a525ACdd2aB3A5Eb5fc9Ab8CF53b881000e
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000bbfb9a525acdd2ab3a5eb5fc9ab8cf53b881000e
Loading...
Loading
Loading...
Loading
Net Worth in USD
$82,963,705.61
Net Worth in ETH
42,495.163653
Token Allocations
PTERIA
100.00%
OKB
0.00%
WETH
0.00%
Others
0.00%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.00 | 22.4063 | $0.00 | |
| ETH | <0.01% | $77.86 | 2.775 | $216.06 | |
| ETH | <0.01% | $1,952.31 | 0.0501 | $97.83 | |
| ETH | <0.01% | $1.31 | 72.5821 | $95.08 | |
| ETH | <0.01% | $1.24 | 74.2581 | $92.08 | |
| ETH | <0.01% | $4.9 | 18.3503 | $89.92 | |
| ETH | <0.01% | $1.8 | 43.9918 | $79.19 | |
| ETH | <0.01% | $1.27 | 53.7 | $68.2 | |
| ETH | <0.01% | $0.347857 | 180.3769 | $62.75 | |
| ETH | <0.01% | $0.00 | 1,130.0192 | $0.00 | |
| ETH | <0.01% | $1.24 | 42.7858 | $53.05 | |
| ETH | <0.01% | $0.00 | 765.6539 | $0.00 | |
| ETH | <0.01% | $3,517.56 | 0.0142 | $49.78 | |
| ETH | <0.01% | $2,297.35 | 0.0211 | $48.57 | |
| ETH | <0.01% | $0.830845 | 51.3987 | $42.7 | |
| ETH | <0.01% | $0.000985 | 42,823.5601 | $42.16 | |
| ETH | <0.01% | $0.99966 | 36.8343 | $36.82 | |
| ETH | <0.01% | $0.079332 | 429.2034 | $34.05 | |
| ETH | <0.01% | $56.93 | 0.593 | $33.76 | |
| ETH | <0.01% | $69.7 | 0.4833 | $33.69 | |
| ETH | <0.01% | $0.017725 | 1,879.9461 | $33.32 | |
| ETH | <0.01% | $1,952.31 | 0.016 | $31.21 | |
| ETH | <0.01% | $0.002402 | 11,907.5843 | $28.61 | |
| ETH | <0.01% | $0.997996 | 27.4417 | $27.39 | |
| ETH | <0.01% | $0.98651 | 25.4063 | $25.06 | |
| ETH | <0.01% | $75,933 | 0.00032998 | $25.06 | |
| ETH | <0.01% | $0.676217 | 35.6262 | $24.09 | |
| ETH | <0.01% | $10.21 | 2.2589 | $23.06 | |
| ETH | <0.01% | $0.071966 | 312.98 | $22.52 | |
| ETH | <0.01% | $1 | 20.923 | $20.96 | |
| ETH | <0.01% | $1.02 | 16.5341 | $16.86 | |
| ETH | <0.01% | $0.136357 | 118.6251 | $16.18 | |
| ETH | <0.01% | $8.37 | 1.9264 | $16.12 | |
| ETH | <0.01% | $0.711897 | 21.6381 | $15.4 | |
| ETH | <0.01% | $71,099 | 0.0002 | $14.22 | |
| ETH | <0.01% | $38.08 | 0.3261 | $12.42 | |
| ETH | <0.01% | $0.004053 | 2,413.5092 | $9.78 | |
| ETH | <0.01% | $0.04191 | 227.5279 | $9.54 | |
| ETH | <0.01% | $0.00 | 0.8016 | $0.00 | |
| ETH | <0.01% | $0.00 | 0.0989 | $0.00 | |
| ETH | <0.01% | $0.001193 | 7,433 | $8.87 | |
| ETH | <0.01% | $0.791778 | 10.9679 | $8.68 | |
| ETH | <0.01% | $0.115189 | 75.3858 | $8.68 | |
| ETH | <0.01% | $0.008529 | 1,014.7299 | $8.65 | |
| ETH | <0.01% | $0.006831 | 1,255.9569 | $8.58 | |
| ETH | <0.01% | $15.45 | 0.551 | $8.51 | |
| ETH | <0.01% | $0.016 | 513.2067 | $8.21 | |
| ETH | <0.01% | $0.172239 | 44.4493 | $7.66 | |
| ETH | <0.01% | $0.00 | 8.8075 | $0.00 | |
| ETH | <0.01% | $0.00 | 658.3512 | $0.00 | |
| ETH | <0.01% | $167.2 | 0.0419 | $7.01 | |
| ETH | <0.01% | $0.000544 | 11,823.855 | $6.44 | |
| ETH | <0.01% | $0.009348 | 667.8693 | $6.24 | |
| ETH | <0.01% | $0.005522 | 1,086.2026 | $6 | |
| ETH | <0.01% | $0.00 | 1.08 | $0.00 | |
| ETH | <0.01% | $0.00 | 91.1202 | $0.00 | |
| ETH | <0.01% | $0.00 | 2.5002 | $0.00 | |
| ETH | <0.01% | $58,411 | 0.00009581 | $5.6 | |
| ETH | <0.01% | $0.00 | 388 | $0.00 | |
| ETH | <0.01% | $0.00 | 350.0843 | $0.00 | |
| ETH | <0.01% | $0.009782 | 543.6171 | $5.32 | |
| ETH | <0.01% | $0.002823 | 1,863.9524 | $5.26 | |
| ETH | <0.01% | $0.007762 | 647.3987 | $5.03 | |
| ETH | <0.01% | $0.054696 | 91.0493 | $4.98 | |
| ETH | <0.01% | $0.00 | 15.3117 | $0.00 | |
| ETH | <0.01% | $0.00 | 2,000 | $0.00 | |
| ETH | <0.01% | $0.038797 | 116.1215 | $4.51 | |
| ETH | <0.01% | $0.337417 | 12.7412 | $4.3 | |
| ETH | <0.01% | $0.00 | 1.4275 | $0.00 | |
| ETH | <0.01% | $0.331276 | 12.2733 | $4.07 | |
| ETH | <0.01% | $0.018036 | 223.7378 | $4.04 | |
| ETH | <0.01% | $1.76 | 2.1573 | $3.8 | |
| ETH | <0.01% | $41.75 | 0.0907 | $3.79 | |
| ETH | <0.01% | $0.007505 | 479.7042 | $3.6 | |
| ETH | <0.01% | $0.013834 | 237.7787 | $3.29 | |
| ETH | <0.01% | $5.16 | 0.6323 | $3.26 | |
| ETH | <0.01% | $0.065419 | 46.8451 | $3.06 | |
| ETH | <0.01% | $98,729 | 0.00003103 | $3.06 | |
| ETH | <0.01% | $0.01121 | 268.613 | $3.01 | |
| ETH | <0.01% | $1.26 | 2.2877 | $2.88 | |
| ETH | <0.01% | $0.003834 | 732.6673 | $2.81 | |
| ETH | <0.01% | $0.00 | 26,697,092,450.3426 | $0.00 | |
| ETH | <0.01% | $0.00 | 2,727.5601 | $0.00 | |
| ETH | <0.01% | $0.005458 | 475.6158 | $2.6 | |
| ETH | <0.01% | $0.005458 | 475.6158 | $2.6 | |
| ETH | <0.01% | $0.102774 | 24.7905 | $2.55 | |
| ETH | <0.01% | $0.02777 | 85.1732 | $2.37 | |
| ETH | <0.01% | $0.001422 | 1,567.7609 | $2.23 | |
| ETH | <0.01% | $0.005981 | 365.77 | $2.19 | |
| ETH | <0.01% | $0.016734 | 124.7587 | $2.09 | |
| ETH | <0.01% | $0.010582 | 195.9431 | $2.07 | |
| ETH | <0.01% | <$0.000001 | 1,808,772,874.5007 | $2.03 | |
| ETH | <0.01% | $0.061154 | 32.621 | $1.99 | |
| ETH | <0.01% | $0.004703 | 422.7673 | $1.99 | |
| ETH | <0.01% | $0.00 | 173.133 | $0.00 | |
| ETH | <0.01% | $0.026706 | 73.7396 | $1.97 | |
| ETH | <0.01% | $9.28 | 0.2096 | $1.94 | |
| ETH | <0.01% | $0.072017 | 26.9145 | $1.94 | |
| ETH | <0.01% | $0.134171 | 14.335 | $1.92 | |
| ETH | <0.01% | $0.009324 | 206.1712 | $1.92 | |
| ETH | <0.01% | $0.576436 | 3.1352 | $1.81 | |
| ETH | <0.01% | $0.088263 | 20 | $1.77 | |
| ETH | <0.01% | $0.000091 | 19,084 | $1.74 | |
| ETH | <0.01% | $0.044935 | 38.0923 | $1.71 | |
| ETH | <0.01% | $1.47 | 1.1568 | $1.7 | |
| ETH | <0.01% | $0.084254 | 20 | $1.69 | |
| ETH | <0.01% | $0.028186 | 59.56 | $1.68 | |
| ETH | <0.01% | $0.19909 | 8.3616 | $1.66 | |
| ETH | <0.01% | $0.001288 | 1,282.5213 | $1.65 | |
| ETH | <0.01% | $0.000073 | 22,387.4272 | $1.64 | |
| ETH | <0.01% | $0.001114 | 1,395.1412 | $1.55 | |
| ETH | <0.01% | $0.24451 | 6.1401 | $1.5 | |
| ETH | <0.01% | $0.0123 | 120.5672 | $1.48 | |
| ETH | <0.01% | $0.011271 | 122.053 | $1.38 | |
| ETH | <0.01% | $0.01335 | 101.9981 | $1.36 | |
| ETH | <0.01% | $0.178595 | 7.5195 | $1.34 | |
| ETH | <0.01% | $0.287472 | 4.3548 | $1.25 | |
| ETH | <0.01% | $0.01835 | 62.6185 | $1.15 | |
| ETH | <0.01% | $0.00 | 88.2167 | $0.00 | |
| ETH | <0.01% | $0.00 | 212.5038 | $0.00 | |
| ETH | <0.01% | $0.000613 | 1,773 | $1.09 | |
| ETH | <0.01% | $0.004085 | 265.2777 | $1.08 | |
| ETH | <0.01% | $0.041173 | 25.9687 | $1.07 | |
| ETH | <0.01% | $0.001506 | 668.0379 | $1.01 | |
| ETH | <0.01% | $0.007406 | 134.5007 | $0.9961 | |
| ETH | <0.01% | $0.051541 | 19.1403 | $0.9865 | |
| ETH | <0.01% | $0.110868 | 8.8536 | $0.9815 | |
| ETH | <0.01% | $0.004939 | 196.2425 | $0.9693 | |
| ETH | <0.01% | $0.00 | 275.2625 | $0.00 | |
| ETH | <0.01% | $0.005945 | 160.4869 | $0.954 | |
| ETH | <0.01% | $0.272966 | 3.47 | $0.9471 | |
| ETH | <0.01% | $0.002561 | 369.7188 | $0.9467 | |
| ETH | <0.01% | $0.004491 | 207.9335 | $0.9339 | |
| ETH | <0.01% | $0.004031 | 231.4677 | $0.9329 | |
| ETH | <0.01% | $0.00 | 4.9834 | $0.00 | |
| ETH | <0.01% | $0.00 | 0.067 | $0.00 | |
| ETH | <0.01% | $0.00 | 1.6542 | $0.00 | |
| ETH | <0.01% | $0.005001 | 169.6039 | $0.8482 | |
| ETH | <0.01% | $0.00 | 129.9968 | $0.00 | |
| ETH | <0.01% | $0.000215 | 3,876.1468 | $0.8325 | |
| ETH | <0.01% | $0.033911 | 24.2669 | $0.8229 | |
| ETH | <0.01% | $0.01599 | 50.9086 | $0.814 | |
| ETH | <0.01% | $0.024296 | 32.528 | $0.7902 | |
| ETH | <0.01% | $0.000007 | 118,764.8453 | $0.7786 | |
| ETH | <0.01% | $0.027662 | 27.5185 | $0.7612 | |
| ETH | <0.01% | $3.98 | 0.1911 | $0.7606 | |
| ETH | <0.01% | $0.001303 | 583.6214 | $0.7601 | |
| ETH | <0.01% | $0.000039 | 19,350 | $0.7599 | |
| ETH | <0.01% | $0.00 | 0.1326 | $0.00 | |
| ETH | <0.01% | $0.278883 | 2.6496 | $0.7389 | |
| ETH | <0.01% | $0.002114 | 336.6311 | $0.7117 | |
| ETH | <0.01% | $0.099171 | 7.0523 | $0.6993 | |
| ETH | <0.01% | $0.00 | 71.5327 | $0.00 | |
| ETH | <0.01% | $12.32 | 0.0551 | $0.6782 | |
| ETH | <0.01% | $0.00 | 6.3373 | $0.00 | |
| ETH | <0.01% | $0.00 | 0.0288 | $0.00 | |
| ETH | <0.01% | $0.188301 | 3.518 | $0.6624 | |
| ETH | <0.01% | $0.602906 | 1.0931 | $0.659 | |
| ETH | <0.01% | $0.000181 | 3,560.2504 | $0.6443 | |
| ETH | <0.01% | $0.021134 | 30.3729 | $0.6418 | |
| ETH | <0.01% | $0.002231 | 283.1861 | $0.6316 | |
| ETH | <0.01% | $0.000374 | 1,687.5532 | $0.6304 | |
| ETH | <0.01% | $0.00 | 18.871 | $0.00 | |
| ETH | <0.01% | $0.00 | 4.8791 | $0.00 | |
| ETH | <0.01% | $0.872146 | 0.677 | $0.5904 | |
| ETH | <0.01% | $0.009908 | 59.5714 | $0.5902 | |
| ETH | <0.01% | $0.00 | 275.8845 | $0.00 | |
| ETH | <0.01% | $0.050319 | 11.4849 | $0.5779 | |
| ETH | <0.01% | $0.092238 | 6.2456 | $0.576 | |
| ETH | <0.01% | $0.00 | 7.6671 | $0.00 | |
| ETH | <0.01% | $0.000389 | 1,440.4247 | $0.56 | |
| ETH | <0.01% | $0.011307 | 49.118 | $0.5553 | |
| ETH | <0.01% | $0.000002 | 264,120.1971 | $0.543 | |
| ETH | <0.01% | $0.357624 | 1.4968 | $0.5352 | |
| ETH | <0.01% | $0.00 | 10.2679 | $0.00 | |
| ETH | <0.01% | $0.00 | 1.0692 | $0.00 | |
| ETH | <0.01% | $1.28 | 0.4025 | $0.5152 | |
| ETH | <0.01% | $0.239483 | 2.1436 | $0.5133 | |
| ETH | <0.01% | $0.002715 | 185.1168 | $0.5024 | |
| ETH | <0.01% | $0.003358 | 148.2669 | $0.4978 | |
| ETH | <0.01% | $0.007055 | 70.4032 | $0.4966 | |
| ETH | <0.01% | $0.007114 | 64.2249 | $0.4569 | |
| ETH | <0.01% | $0.00048 | 952.5484 | $0.4568 | |
| ETH | <0.01% | $0.076193 | 5.9557 | $0.4537 | |
| ETH | <0.01% | $0.000265 | 1,688.2342 | $0.4468 | |
| ETH | <0.01% | $0.00 | 1,565.3958 | $0.00 | |
| ETH | <0.01% | $0.000601 | 719.6418 | $0.4327 | |
| ETH | <0.01% | $0.676333 | 0.6382 | $0.4316 | |
| ETH | <0.01% | $0.00 | 76,121.4608 | $0.00 | |
| ETH | <0.01% | $0.007635 | 54.4667 | $0.4158 | |
| ETH | <0.01% | $0.001539 | 270.1487 | $0.4156 | |
| ETH | <0.01% | $0.004045 | 101.3385 | $0.4099 | |
| ETH | <0.01% | $0.00 | 5.4223 | $0.00 | |
| ETH | <0.01% | $0.000078 | 5,198.9924 | $0.4032 | |
| ETH | <0.01% | $0.054918 | 7.3126 | $0.4015 | |
| ETH | <0.01% | $0.014018 | 27.9908 | $0.3923 | |
| ETH | <0.01% | $0.003839 | 98.274 | $0.3772 | |
| ETH | <0.01% | $0.000422 | 862.7314 | $0.3641 | |
| ETH | <0.01% | $0.00 | 0.0106 | $0.00 | |
| ETH | <0.01% | $0.00 | 0.00551563 | $0.00 | |
| ETH | <0.01% | $0.000493 | 718.1862 | $0.3541 | |
| ETH | <0.01% | $0.000005 | 65,494.7883 | $0.3458 | |
| ETH | <0.01% | $0.116238 | 2.9501 | $0.3429 | |
| ETH | <0.01% | $0.002524 | 135.6106 | $0.3422 | |
| ETH | <0.01% | $0.000081 | 4,112.9368 | $0.3322 | |
| ETH | <0.01% | $0.000022 | 14,367 | $0.3209 | |
| ETH | <0.01% | $0.01508 | 20.8021 | $0.3137 | |
| ETH | <0.01% | $0.005787 | 51.7149 | $0.2992 | |
| ETH | <0.01% | $0.001714 | 174.0074 | $0.2982 | |
| ETH | <0.01% | $0.039922 | 7.4542 | $0.2975 | |
| ETH | <0.01% | $0.037222 | 7.9218 | $0.2948 | |
| ETH | <0.01% | $0.753113 | 0.3597 | $0.2709 | |
| ETH | <0.01% | $3.32 | 0.0806 | $0.2677 | |
| ETH | <0.01% | $0.000309 | 847.0283 | $0.2616 | |
| ETH | <0.01% | $0.001005 | 245.4289 | $0.2466 | |
| ETH | <0.01% | $0.031325 | 7.8648 | $0.2463 | |
| ETH | <0.01% | $0.000504 | 487.7617 | $0.2456 | |
| ETH | <0.01% | <$0.000001 | 2,724,518,843.6435 | $0.2446 | |
| ETH | <0.01% | $0.000008 | 30,654.6569 | $0.243 | |
| ETH | <0.01% | $3.53 | 0.0652 | $0.2301 | |
| ETH | <0.01% | $0.100043 | 2.2909 | $0.2291 | |
| ETH | <0.01% | $0.001182 | 191.4078 | $0.2262 | |
| ETH | <0.01% | $0.00 | 158.2782 | $0.00 | |
| ETH | <0.01% | $0.00 | 1.6103 | $0.00 | |
| ETH | <0.01% | $0.00 | 34.3644 | $0.00 | |
| ETH | <0.01% | $0.00 | 2.0793 | $0.00 | |
| ETH | <0.01% | $0.026301 | 6.7931 | $0.1786 | |
| ETH | <0.01% | $0.028326 | 6.3053 | $0.1786 | |
| ETH | <0.01% | $0.00089 | 200.5839 | $0.1784 | |
| ETH | <0.01% | $0.000405 | 434.0236 | $0.1758 | |
| ETH | <0.01% | $0.000001 | 227,057.6613 | $0.172 | |
| ETH | <0.01% | $0.001241 | 132.288 | $0.1642 | |
| ETH | <0.01% | $7.13 | 0.023 | $0.1637 | |
| ETH | <0.01% | $0.009992 | 15.7357 | $0.1572 | |
| ETH | <0.01% | $0.00026 | 599.042 | $0.1556 | |
| ETH | <0.01% | $0.001996 | 75.968 | $0.1516 | |
| ETH | <0.01% | $0.027138 | 5.581 | $0.1514 | |
| ETH | <0.01% | $0.002548 | 58.5204 | $0.149 | |
| ETH | <0.01% | $0.000035 | 4,116.0755 | $0.1455 | |
| ETH | <0.01% | $0.00244 | 59.4548 | $0.145 | |
| ETH | <0.01% | $0.000519 | 276.7151 | $0.1434 | |
| ETH | <0.01% | $0.008131 | 16.469 | $0.1339 | |
| ETH | <0.01% | $0.054959 | 2.4205 | $0.133 | |
| ETH | <0.01% | $0.000001 | 188,474.7607 | $0.1316 | |
| ETH | <0.01% | $0.00 | 1.413 | $0.00 | |
| ETH | <0.01% | $0.000192 | 678.81 | $0.1303 | |
| ETH | <0.01% | $0.001301 | 96.3213 | $0.1252 | |
| ETH | <0.01% | $0.000142 | 884.2138 | $0.1251 | |
| ETH | <0.01% | $0.023505 | 5.2533 | $0.1234 | |
| ETH | <0.01% | $0.000002 | 60,430.5356 | $0.1166 | |
| ETH | <0.01% | $0.000079 | 1,473.919 | $0.1164 | |
| ETH | <0.01% | $0.00 | 1.8782 | $0.00 | |
| ETH | <0.01% | $0.003082 | 35.4469 | $0.1092 | |
| ETH | <0.01% | $0.00098 | 109.5242 | $0.1073 | |
| ETH | <0.01% | $0.257495 | 0.4086 | $0.1052 | |
| ETH | <0.01% | $0.000619 | 169.1557 | $0.1046 | |
| ETH | <0.01% | $0.342973 | 0.2999 | $0.1028 | |
| BSC | <0.01% | $0.008296 | 1,501.6874 | $12.46 | |
| BSC | <0.01% | $0.000028 | 320,084.5354 | $9.09 | |
| BSC | <0.01% | $0.011693 | 122.053 | $1.43 | |
| BSC | <0.01% | $613.82 | 0.00172114 | $1.06 | |
| BSC | <0.01% | $0.028616 | 16.9672 | $0.4855 | |
| BSC | <0.01% | $0.000702 | 286.07 | $0.2008 | |
| BASE | <0.01% | $0.019895 | 160 | $3.18 | |
| BASE | <0.01% | $1,952.3 | 0.00001 | $0.019523 | |
| OP | <0.01% | $1 | 0.7322 | $0.7322 | |
| POL | <0.01% | $0.000081 | 2,122.7779 | $0.1729 | |
| POL | <0.01% | $0.005729 | 19.5467 | $0.1119 | |
| POL | <0.01% | $0.10767 | 0.0005 | $0.000054 | |
| GNO | <0.01% | $0.999735 | 0.000000000000002511 | <$0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.