Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60e06040 | 18627864 | 813 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CowswapOrderSigner
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
// implementation based on https://gist.github.com/Arachnid/6950b3367258b5d5033f6e1c411086e8
// cowswap contracts taken from https://github.com/cowprotocol/contracts/releases/tag/v1.3.2
pragma solidity ^0.8.12;
import "./cowProtocol/libraries/GPv2Order.sol";
import "./cowProtocol/mixins/GPv2Signing.sol";
import "./cowProtocol/interfaces/IERC20.sol";
contract CowswapOrderSigner {
using GPv2Order for GPv2Order.Data;
using GPv2Order for bytes;
GPv2Signing public immutable signing;
bytes32 public immutable domainSeparator;
address public immutable deployedAt;
constructor(GPv2Signing _signing) {
require(address(_signing) != address(0), "Invalid signing address");
signing = _signing;
domainSeparator = _signing.domainSeparator();
deployedAt = address(this);
}
function _setPreSignature(
GPv2Order.Data calldata order,
bool signed
) internal {
require(address(this) != deployedAt, "DELEGATECALL only");
// compute order UID
bytes32 orderDigest = order.hash(domainSeparator);
bytes memory orderUid = new bytes(GPv2Order.UID_LENGTH);
orderUid.packOrderUidParams(orderDigest, address(this), order.validTo);
signing.setPreSignature(orderUid, signed);
}
function signOrder(
GPv2Order.Data calldata order,
uint32 validDuration, // seconds
uint256 feeAmountBP // basis points
) external {
require(
block.timestamp + validDuration > order.validTo,
"Dishonest valid duration"
);
require(
order.feeAmount <= (order.sellAmount * feeAmountBP) / 100_00 + 1,
"Fee too high"
);
_setPreSignature(order, true);
}
function unsignOrder(GPv2Order.Data calldata order) external {
_setPreSignature(order, false);
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.12;
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: MIT
// Vendored from OpenZeppelin contracts with minor modifications:
// - Modified Solidity version
// - Formatted code
// - Added `name`, `symbol` and `decimals` function declarations
// <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/token/ERC20/IERC20.sol>
pragma solidity ^0.8.12;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the number of decimals the token uses.
*/
function decimals() external view returns (uint8);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount)
external
returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender)
external
view
returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.12;
import "../interfaces/IERC20.sol";
/// @title Gnosis Protocol v2 Order Library
/// @author Gnosis Developers
library GPv2Order {
/// @dev The complete data for a Gnosis Protocol order. This struct contains
/// all order parameters that are signed for submitting to GP.
struct Data {
IERC20 sellToken;
IERC20 buyToken;
address receiver;
uint256 sellAmount;
uint256 buyAmount;
uint32 validTo;
bytes32 appData;
uint256 feeAmount;
bytes32 kind;
bool partiallyFillable;
bytes32 sellTokenBalance;
bytes32 buyTokenBalance;
}
/// @dev The order EIP-712 type hash for the [`GPv2Order.Data`] struct.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256(
/// "Order(" +
/// "address sellToken," +
/// "address buyToken," +
/// "address receiver," +
/// "uint256 sellAmount," +
/// "uint256 buyAmount," +
/// "uint32 validTo," +
/// "bytes32 appData," +
/// "uint256 feeAmount," +
/// "string kind," +
/// "bool partiallyFillable," +
/// "string sellTokenBalance," +
/// "string buyTokenBalance" +
/// ")"
/// )
/// ```
bytes32 internal constant TYPE_HASH =
hex"d5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e489";
/// @dev The marker value for a sell order for computing the order struct
/// hash. This allows the EIP-712 compatible wallets to display a
/// descriptive string for the order kind (instead of 0 or 1).
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("sell")
/// ```
bytes32 internal constant KIND_SELL =
hex"f3b277728b3fee749481eb3e0b3b48980dbbab78658fc419025cb16eee346775";
/// @dev The OrderKind marker value for a buy order for computing the order
/// struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("buy")
/// ```
bytes32 internal constant KIND_BUY =
hex"6ed88e868af0a1983e3886d5f3e95a2fafbd6c3450bc229e27342283dc429ccc";
/// @dev The TokenBalance marker value for using direct ERC20 balances for
/// computing the order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("erc20")
/// ```
bytes32 internal constant BALANCE_ERC20 =
hex"5a28e9363bb942b639270062aa6bb295f434bcdfc42c97267bf003f272060dc9";
/// @dev The TokenBalance marker value for using Balancer Vault external
/// balances (in order to re-use Vault ERC20 approvals) for computing the
/// order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("external")
/// ```
bytes32 internal constant BALANCE_EXTERNAL =
hex"abee3b73373acd583a130924aad6dc38cfdc44ba0555ba94ce2ff63980ea0632";
/// @dev The TokenBalance marker value for using Balancer Vault internal
/// balances for computing the order struct hash.
///
/// This value is pre-computed from the following expression:
/// ```
/// keccak256("internal")
/// ```
bytes32 internal constant BALANCE_INTERNAL =
hex"4ac99ace14ee0a5ef932dc609df0943ab7ac16b7583634612f8dc35a4289a6ce";
/// @dev Marker address used to indicate that the receiver of the trade
/// proceeds should the owner of the order.
///
/// This is chosen to be `address(0)` for gas efficiency as it is expected
/// to be the most common case.
address internal constant RECEIVER_SAME_AS_OWNER = address(0);
/// @dev The byte length of an order unique identifier.
uint256 internal constant UID_LENGTH = 56;
/// @dev Returns the actual receiver for an order. This function checks
/// whether or not the [`receiver`] field uses the marker value to indicate
/// it is the same as the order owner.
///
/// @return receiver The actual receiver of trade proceeds.
function actualReceiver(Data memory order, address owner)
internal
pure
returns (address receiver)
{
if (order.receiver == RECEIVER_SAME_AS_OWNER) {
receiver = owner;
} else {
receiver = order.receiver;
}
}
/// @dev Return the EIP-712 signing hash for the specified order.
///
/// @param order The order to compute the EIP-712 signing hash for.
/// @param domainSeparator The EIP-712 domain separator to use.
/// @return orderDigest The 32 byte EIP-712 struct hash.
function hash(Data memory order, bytes32 domainSeparator)
internal
pure
returns (bytes32 orderDigest)
{
bytes32 structHash;
// NOTE: Compute the EIP-712 order struct hash in place. As suggested
// in the EIP proposal, noting that the order struct has 12 fields, and
// prefixing the type hash `(1 + 12) * 32 = 416` bytes to hash.
// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-encodedata>
// solhint-disable-next-line no-inline-assembly
assembly {
let dataStart := sub(order, 32)
let temp := mload(dataStart)
mstore(dataStart, TYPE_HASH)
structHash := keccak256(dataStart, 416)
mstore(dataStart, temp)
}
// NOTE: Now that we have the struct hash, compute the EIP-712 signing
// hash using scratch memory past the free memory pointer. The signing
// hash is computed from `"\x19\x01" || domainSeparator || structHash`.
// <https://docs.soliditylang.org/en/v0.7.6/internals/layout_in_memory.html#layout-in-memory>
// <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification>
// solhint-disable-next-line no-inline-assembly
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, "\x19\x01")
mstore(add(freeMemoryPointer, 2), domainSeparator)
mstore(add(freeMemoryPointer, 34), structHash)
orderDigest := keccak256(freeMemoryPointer, 66)
}
}
/// @dev Packs order UID parameters into the specified memory location. The
/// result is equivalent to `abi.encodePacked(...)` with the difference that
/// it allows re-using the memory for packing the order UID.
///
/// This function reverts if the order UID buffer is not the correct size.
///
/// @param orderUid The buffer pack the order UID parameters into.
/// @param orderDigest The EIP-712 struct digest derived from the order
/// parameters.
/// @param owner The address of the user who owns this order.
/// @param validTo The epoch time at which the order will stop being valid.
function packOrderUidParams(
bytes memory orderUid,
bytes32 orderDigest,
address owner,
uint32 validTo
) internal pure {
require(orderUid.length == UID_LENGTH, "GPv2: uid buffer overflow");
// NOTE: Write the order UID to the allocated memory buffer. The order
// parameters are written to memory in **reverse order** as memory
// operations write 32-bytes at a time and we want to use a packed
// encoding. This means, for example, that after writing the value of
// `owner` to bytes `20:52`, writing the `orderDigest` to bytes `0:32`
// will **overwrite** bytes `20:32`. This is desirable as addresses are
// only 20 bytes and `20:32` should be `0`s:
//
// | 1111111111222222222233333333334444444444555555
// byte | 01234567890123456789012345678901234567890123456789012345
// -------+---------------------------------------------------------
// field | [.........orderDigest..........][......owner.......][vT]
// -------+---------------------------------------------------------
// mstore | [000000000000000000000000000.vT]
// | [00000000000.......owner.......]
// | [.........orderDigest..........]
//
// Additionally, since Solidity `bytes memory` are length prefixed,
// 32 needs to be added to all the offsets.
//
// solhint-disable-next-line no-inline-assembly
assembly {
mstore(add(orderUid, 56), validTo)
mstore(add(orderUid, 52), owner)
mstore(add(orderUid, 32), orderDigest)
}
}
/// @dev Extracts specific order information from the standardized unique
/// order id of the protocol.
///
/// @param orderUid The unique identifier used to represent an order in
/// the protocol. This uid is the packed concatenation of the order digest,
/// the validTo order parameter and the address of the user who created the
/// order. It is used by the user to interface with the contract directly,
/// and not by calls that are triggered by the solvers.
/// @return orderDigest The EIP-712 signing digest derived from the order
/// parameters.
/// @return owner The address of the user who owns this order.
/// @return validTo The epoch time at which the order will stop being valid.
function extractOrderUidParams(bytes calldata orderUid)
internal
pure
returns (
bytes32 orderDigest,
address owner,
uint32 validTo
)
{
require(orderUid.length == UID_LENGTH, "GPv2: invalid uid");
// Use assembly to efficiently decode packed calldata.
// solhint-disable-next-line no-inline-assembly
assembly {
orderDigest := calldataload(orderUid.offset)
owner := shr(96, calldataload(add(orderUid.offset, 32)))
validTo := shr(224, calldataload(add(orderUid.offset, 52)))
}
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.12;
import "../interfaces/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,
order.sellTokenBalance,
order.buyTokenBalance,
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 ... | 6 | 5 | 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
/// | | | | |
/// | | | +---+------------ use internal sell token balance bit:
/// | | | 0x: ERC20 token balance
/// | | | 10: external Balancer Vault balance
/// | | | 11: internal Balancer Vault balance
/// | | |
/// | | +-------------------- use buy token balance bit
/// | | 0: ERC20 token balance
/// | | 1: internal Balancer Vault balance
/// | |
/// +---+------------------------ 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,
bytes32 sellTokenBalance,
bytes32 buyTokenBalance,
GPv2Signing.Scheme signingScheme
)
{
if (flags & 0x01 == 0) {
kind = GPv2Order.KIND_SELL;
} else {
kind = GPv2Order.KIND_BUY;
}
partiallyFillable = flags & 0x02 != 0;
if (flags & 0x08 == 0) {
sellTokenBalance = GPv2Order.BALANCE_ERC20;
} else if (flags & 0x04 == 0) {
sellTokenBalance = GPv2Order.BALANCE_EXTERNAL;
} else {
sellTokenBalance = GPv2Order.BALANCE_INTERNAL;
}
if (flags & 0x10 == 0) {
buyTokenBalance = GPv2Order.BALANCE_ERC20;
} else {
buyTokenBalance = GPv2Order.BALANCE_INTERNAL;
}
// 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 >> 5);
}
}// SPDX-License-Identifier: LGPL-3.0-or-later
pragma solidity ^0.8.12;
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.
/// @param signed True to set the order as tradable with pre-sign, false to
/// false to unset it.
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"
);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract GPv2Signing","name":"_signing","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"deployedAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"},{"internalType":"uint32","name":"validDuration","type":"uint32"},{"internalType":"uint256","name":"feeAmountBP","type":"uint256"}],"name":"signOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signing","outputs":[{"internalType":"contract GPv2Signing","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"sellToken","type":"address"},{"internalType":"contract IERC20","name":"buyToken","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint32","name":"validTo","type":"uint32"},{"internalType":"bytes32","name":"appData","type":"bytes32"},{"internalType":"uint256","name":"feeAmount","type":"uint256"},{"internalType":"bytes32","name":"kind","type":"bytes32"},{"internalType":"bool","name":"partiallyFillable","type":"bool"},{"internalType":"bytes32","name":"sellTokenBalance","type":"bytes32"},{"internalType":"bytes32","name":"buyTokenBalance","type":"bytes32"}],"internalType":"struct GPv2Order.Data","name":"order","type":"tuple"}],"name":"unsignOrder","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60e060405234801561001057600080fd5b506040516108a03803806108a083398101604081905261002f91610104565b6001600160a01b0381166100895760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964207369676e696e672061646472657373000000000000000000604482015260640160405180910390fd5b6001600160a01b03811660808190526040805163f698da2560e01b8152905163f698da25916004808201926020929091908290030181865afa1580156100d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f79190610134565b60a052503060c05261014d565b60006020828403121561011657600080fd5b81516001600160a01b038116811461012d57600080fd5b9392505050565b60006020828403121561014657600080fd5b5051919050565b60805160a05160c05161071261018e6000396000818160cd015261022f01526000818160f401526102980152600081816089015261037001526107126000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c8063569d34891461005c5780635a66c223146100715780638302757a14610084578063eae4c19f146100c8578063f698da25146100ef575b600080fd5b61006f61006a366004610474565b610124565b005b61006f61007f3660046104b4565b610216565b6100ab7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ab7f000000000000000000000000000000000000000000000000000000000000000081565b6101167f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020016100bf565b61013460c0840160a085016104d8565b63ffffffff168263ffffffff164261014c9190610509565b1161019e5760405162461bcd60e51b815260206004820152601860248201527f446973686f6e6573742076616c6964206475726174696f6e000000000000000060448201526064015b60405180910390fd5b6127106101af826060860135610521565b6101b99190610540565b6101c4906001610509565b8360e0013511156102065760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606401610195565b610211836001610224565b505050565b610221816000610224565b50565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614156102915760405162461bcd60e51b815260206004820152601160248201527044454c454741544543414c4c206f6e6c7960781b6044820152606401610195565b60006103157f00000000000000000000000000000000000000000000000000000000000000006102c6368690038601866105c1565b601f190180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b8152600281019290925260228201526042902090565b6040805160388082526060820190925291925060009190602082018180368337019050509050610359823061035060c0880160a089016104d8565b849291906103df565b60405163ec6cb13f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ec6cb13f906103a7908490879060040161067f565b600060405180830381600087803b1580156103c157600080fd5b505af11580156103d5573d6000803e3d6000fd5b5050505050505050565b60388451146104305760405162461bcd60e51b815260206004820152601960248201527f475076323a2075696420627566666572206f766572666c6f77000000000000006044820152606401610195565b60388401526034830152602090910152565b6000610180828403121561045557600080fd5b50919050565b803563ffffffff8116811461046f57600080fd5b919050565b60008060006101c0848603121561048a57600080fd5b6104948585610442565b92506104a3610180850161045b565b91506101a084013590509250925092565b600061018082840312156104c757600080fd5b6104d18383610442565b9392505050565b6000602082840312156104ea57600080fd5b6104d18261045b565b634e487b7160e01b600052601160045260246000fd5b6000821982111561051c5761051c6104f3565b500190565b600081600019048311821515161561053b5761053b6104f3565b500290565b60008261055d57634e487b7160e01b600052601260045260246000fd5b500490565b604051610180810167ffffffffffffffff8111828210171561059457634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160a01b038116811461046f57600080fd5b8035801515811461046f57600080fd5b600061018082840312156105d457600080fd5b6105dc610562565b6105e58361059a565b81526105f36020840161059a565b60208201526106046040840161059a565b6040820152606083013560608201526080830135608082015261062960a0840161045b565b60a082015260c083013560c082015260e083013560e082015261010080840135818301525061012061065c8185016105b1565b908201526101408381013590820152610160928301359281019290925250919050565b604081526000835180604084015260005b818110156106ad5760208187018101516060868401015201610690565b818111156106bf576000606083860101525b50921515602083015250601f91909101601f19160160600191905056fea26469706673582212209492c82cd1530f2d2d13fb87c4631f1db3a91a6c67f6f86df5d017ec7bb9967f64736f6c634300080c00330000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100575760003560e01c8063569d34891461005c5780635a66c223146100715780638302757a14610084578063eae4c19f146100c8578063f698da25146100ef575b600080fd5b61006f61006a366004610474565b610124565b005b61006f61007f3660046104b4565b610216565b6100ab7f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab4181565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ab7f00000000000000000000000023da9ade38e4477b23770ded512fd37b12381fab81565b6101167fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e894381565b6040519081526020016100bf565b61013460c0840160a085016104d8565b63ffffffff168263ffffffff164261014c9190610509565b1161019e5760405162461bcd60e51b815260206004820152601860248201527f446973686f6e6573742076616c6964206475726174696f6e000000000000000060448201526064015b60405180910390fd5b6127106101af826060860135610521565b6101b99190610540565b6101c4906001610509565b8360e0013511156102065760405162461bcd60e51b815260206004820152600c60248201526b08ccaca40e8dede40d0d2ced60a31b6044820152606401610195565b610211836001610224565b505050565b610221816000610224565b50565b306001600160a01b037f00000000000000000000000023da9ade38e4477b23770ded512fd37b12381fab1614156102915760405162461bcd60e51b815260206004820152601160248201527044454c454741544543414c4c206f6e6c7960781b6044820152606401610195565b60006103157fc078f884a2676e1345748b1feace7b0abee5d00ecadb6e574dcdd109a63e89436102c6368690038601866105c1565b601f190180517fd5a25ba2e97094ad7d83dc28a6572da797d6b3e7fc6663bd93efb789fc17e48982526101a08220915260405161190160f01b8152600281019290925260228201526042902090565b6040805160388082526060820190925291925060009190602082018180368337019050509050610359823061035060c0880160a089016104d8565b849291906103df565b60405163ec6cb13f60e01b81526001600160a01b037f0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41169063ec6cb13f906103a7908490879060040161067f565b600060405180830381600087803b1580156103c157600080fd5b505af11580156103d5573d6000803e3d6000fd5b5050505050505050565b60388451146104305760405162461bcd60e51b815260206004820152601960248201527f475076323a2075696420627566666572206f766572666c6f77000000000000006044820152606401610195565b60388401526034830152602090910152565b6000610180828403121561045557600080fd5b50919050565b803563ffffffff8116811461046f57600080fd5b919050565b60008060006101c0848603121561048a57600080fd5b6104948585610442565b92506104a3610180850161045b565b91506101a084013590509250925092565b600061018082840312156104c757600080fd5b6104d18383610442565b9392505050565b6000602082840312156104ea57600080fd5b6104d18261045b565b634e487b7160e01b600052601160045260246000fd5b6000821982111561051c5761051c6104f3565b500190565b600081600019048311821515161561053b5761053b6104f3565b500290565b60008261055d57634e487b7160e01b600052601260045260246000fd5b500490565b604051610180810167ffffffffffffffff8111828210171561059457634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160a01b038116811461046f57600080fd5b8035801515811461046f57600080fd5b600061018082840312156105d457600080fd5b6105dc610562565b6105e58361059a565b81526105f36020840161059a565b60208201526106046040840161059a565b6040820152606083013560608201526080830135608082015261062960a0840161045b565b60a082015260c083013560c082015260e083013560e082015261010080840135818301525061012061065c8185016105b1565b908201526101408381013590820152610160928301359281019290925250919050565b604081526000835180604084015260005b818110156106ad5760208187018101516060868401015201610690565b818111156106bf576000606083860101525b50921515602083015250601f91909101601f19160160600191905056fea26469706673582212209492c82cd1530f2d2d13fb87c4631f1db3a91a6c67f6f86df5d017ec7bb9967f64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41
-----Decoded View---------------
Arg [0] : _signing (address): 0x9008D19f58AAbD9eD0D60971565AA8510560ab41
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000009008d19f58aabd9ed0d60971565aa8510560ab41
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.