Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
ZigZagExchange
Compiler Version
v0.8.10+commit.fc410830
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import './LibOrder.sol'; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { EIP712 } from '@openzeppelin/contracts/utils/cryptography/EIP712.sol'; import { SignatureChecker } from '@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol'; //import "hardhat/console.sol"; contract ZigZagExchange is EIP712 { event Swap( address maker, address taker, address makerSellToken, address takerSellToken, uint256 makerSellAmount, uint256 takerSellAmount, uint256 makerVolumeFee, uint256 takerVolumeFee ); mapping(bytes32 => uint256) public filled; mapping(bytes32 => bool) public cancelled; // fees address FEE_ADDRESS; uint256 maker_fee_numerator = 0; uint256 maker_fee_denominator = 10000; uint256 taker_fee_numerator = 5; uint256 taker_fee_denominator = 10000; // initialize fee address constructor( string memory name, string memory version, address fee_address ) EIP712(name, version) { FEE_ADDRESS = fee_address; } // Canceling an order prevents it from being filled function cancelOrder(LibOrder.Order memory order) public { require(msg.sender == order.user, 'only user may cancel order'); bytes32 orderHash = LibOrder.getOrderHash(order); require(filled[orderHash] < order.sellAmount, 'order already filled'); cancelled[orderHash] = true; } // Canceling an order prevents it from being filled // This is for smart contracts to be able to sign order cancels function cancelOrderWithSig(LibOrder.Order memory order, bytes memory cancelSignature) public { bytes32 orderHash = LibOrder.getOrderHash(order); require(filled[orderHash] < order.sellAmount, 'order already filled'); bytes32 cancelHash = LibOrder.getCancelOrderHash(orderHash); require(_isValidSignatureHash(order.user, cancelHash, cancelSignature), "invalid cancel signature"); cancelled[orderHash] = true; } // fillAmount is the amount of the makerOrder.sellAmount to fill // (fillAvailable = true) fills whatever is available if the makerOrder.sellAmount < fillAmount function fillOrder( LibOrder.Order memory makerOrder, bytes memory makerSignature, uint fillAmount, bool fillAvailable ) public returns (bool) { require(msg.sender != makerOrder.user, 'self swap not allowed'); LibOrder.OrderInfo memory makerOrderInfo = getOpenOrder(makerOrder); //validate signature require(_isValidSignatureHash(makerOrder.user, makerOrderInfo.orderHash, makerSignature), 'invalid maker signature'); // adjust size if the user wants to fill whatever is available uint availableSize = makerOrder.sellAmount - makerOrderInfo.orderSellFilledAmount; if (fillAvailable && availableSize < fillAmount) fillAmount = availableSize; require(fillAmount <= availableSize, 'fill amount exceeds available size'); uint buyAmount = fillAmount * makerOrder.buyAmount / makerOrder.sellAmount; // Verify balances require(IERC20(makerOrder.buyToken).balanceOf(msg.sender) >= buyAmount, 'taker order not enough balance'); require(IERC20(makerOrder.sellToken).balanceOf(makerOrder.user) >= fillAmount, 'maker order not enough balance'); // mark fills in storage filled[makerOrderInfo.orderHash] += fillAmount; _settleMatchedOrders( makerOrder.user, msg.sender, makerOrder.sellToken, makerOrder.buyToken, fillAmount, buyAmount ); return true; } function matchOrders( LibOrder.Order memory makerOrder, LibOrder.Order memory takerOrder, bytes memory makerSignature, bytes memory takerSignature ) public returns (bool) { // check that tokens address match require(takerOrder.sellToken == makerOrder.buyToken, 'mismatched tokens'); require(takerOrder.buyToken == makerOrder.sellToken, 'mismatched tokens'); // no self-swap require(takerOrder.user != makerOrder.user, 'self swap not allowed'); LibOrder.OrderInfo memory makerOrderInfo = getOpenOrder(makerOrder); LibOrder.OrderInfo memory takerOrderInfo = getOpenOrder(takerOrder); //validate signature require(_isValidSignatureHash(takerOrder.user, takerOrderInfo.orderHash, takerSignature), 'invalid taker signature'); require(_isValidSignatureHash(makerOrder.user, makerOrderInfo.orderHash, makerSignature), 'invalid maker signature'); // Make sure both orders are crossed. // The orders are crossed if the cost per unit bought (OrderA.SellAmount/OrderA.BuyAmount) for **each** order is greater // than the profit per unit sold of the matched order (OrderB.BuyAmount/OrderB.SellAmount). // This is satisfied by the equations below: // <makerOrder.sellAmount> / <makerOrder.buyAmount> >= <takerOrder.buyAmount> / <takerOrder.sellAmount> // AND // <takerOrder.sellAmount> / <takerOrder.buyAmount> >= <makerOrder.buyAmount> / <makerOrder.sellAmount> // These equations can be combined to get the following: require(makerOrder.sellAmount * takerOrder.sellAmount >= makerOrder.buyAmount * takerOrder.buyAmount, 'orders not crossed'); // Calculate the maximum fill results for the maker and taker assets. At least one of the orders will be fully filled. // // The maximum that the maker maker can possibly buy is the amount that the taker order can sell. // The maximum that the taker maker can possibly buy is the amount that the maker order can sell. // // There are two cases to consider: // Case 1. // If the maker can buy more or the same as the taker can sell, then the taker order is fully filled, at the price of the maker order. // Case 2. // Else the taker can buy more or the same as the maker can sell, then the maker order is fully filled, at the price of the maker order. uint makerSellAmountRemaining = makerOrder.sellAmount - makerOrderInfo.orderSellFilledAmount; uint takerSellAmountRemaining = takerOrder.sellAmount - takerOrderInfo.orderSellFilledAmount; uint makerBuyAmountRemaining = makerSellAmountRemaining * makerOrder.buyAmount / makerOrder.sellAmount; uint makerSellAmount; uint takerSellAmount; if (makerBuyAmountRemaining >= takerSellAmountRemaining) { makerSellAmount = takerSellAmountRemaining * makerOrder.sellAmount / makerOrder.buyAmount; takerSellAmount = takerSellAmountRemaining; } else { makerSellAmount = makerSellAmountRemaining; takerSellAmount = makerBuyAmountRemaining; } // Verify balances require(IERC20(takerOrder.sellToken).balanceOf(takerOrder.user) >= takerSellAmount, 'taker order not enough balance'); require(IERC20(makerOrder.sellToken).balanceOf(makerOrder.user) >= makerSellAmount, 'maker order not enough balance'); // mark fills in storage filled[LibOrder.getOrderHash(makerOrder)] += makerSellAmount; filled[LibOrder.getOrderHash(takerOrder)] += takerSellAmount; _settleMatchedOrders( makerOrder.user, takerOrder.user, makerOrder.sellToken, takerOrder.sellToken, makerSellAmount, takerSellAmount ); return true; } function _settleMatchedOrders( address maker, address taker, address makerSellToken, address takerSellToken, uint makerSellAmount, uint takerSellAmount ) internal { // The fee gets subtracted from the buy amounts so they deduct from the total instead of adding on to it // The taker fee comes out of the maker sell quantity, so the taker ends up with less // The maker fee comes out of the taker sell quantity, so the maker ends up with less // takerBuyAmount = makerSellAmount // makerBuyAmount = takerSellAmount uint takerFee = makerSellAmount * taker_fee_numerator / taker_fee_denominator; uint makerFee = takerSellAmount * maker_fee_numerator / maker_fee_denominator; // Taker fee -> fee recipient if (takerFee > 0) { IERC20(makerSellToken).transferFrom(maker, FEE_ADDRESS, takerFee); } // Maker fee -> fee recipient if (makerFee > 0) { IERC20(takerSellToken).transferFrom(taker, FEE_ADDRESS, makerFee); } // taker -> maker IERC20(takerSellToken).transferFrom(taker, maker, takerSellAmount - makerFee); // maker -> taker IERC20(makerSellToken).transferFrom(maker, taker, makerSellAmount - takerFee); emit Swap( maker, taker, makerSellToken, takerSellToken, makerSellAmount, takerSellAmount, makerFee, takerFee ); } function getOpenOrder(LibOrder.Order memory order) public view returns (LibOrder.OrderInfo memory orderInfo) { orderInfo.orderHash = LibOrder.getOrderHash(order); orderInfo.orderSellFilledAmount = filled[orderInfo.orderHash]; require(orderInfo.orderSellFilledAmount < order.sellAmount, 'order is filled'); require(block.timestamp <= order.expirationTimeSeconds, 'order expired'); require(!cancelled[orderInfo.orderHash], 'order canceled'); } function isValidOrderSignature(LibOrder.Order memory order, bytes memory signature) public view returns (bool) { bytes32 orderHash = LibOrder.getOrderHash(order); return _isValidSignatureHash(order.user, orderHash, signature); } function isValidCancelSignature(LibOrder.Order memory order, bytes memory signature) public view returns (bool) { bytes32 orderHash = LibOrder.getOrderHash(order); bytes32 cancelHash = LibOrder.getCancelOrderHash(orderHash); return _isValidSignatureHash(order.user, cancelHash, signature); } // hash can be an order hash or a cancel order hash function _isValidSignatureHash( address user, bytes32 hash, bytes memory signature ) private view returns (bool) { bytes32 digest = _hashTypedDataV4(hash); return SignatureChecker.isValidSignatureNow(user, digest, signature); } function setFees( uint256 _taker_fee_numerator, uint256 _taker_fee_denominator, uint256 _maker_fee_numerator, uint256 _maker_fee_denominator ) public { require(msg.sender == FEE_ADDRESS, 'only fee address may update fees'); taker_fee_numerator = _taker_fee_numerator; taker_fee_denominator = _taker_fee_denominator; maker_fee_numerator = _maker_fee_numerator; maker_fee_denominator = _maker_fee_denominator; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library LibOrder { //keccak256("Order(address user,address sellToken,address buyToken,uint256 sellAmount,uint256 buyAmount,uint256 expirationTimeSeconds)") bytes32 internal constant _EIP712_ORDER_SCHEMA_HASH = 0x68d868c8698fc31da3a36bb7a184a4af099797794701bae97bea3de7ebe6e399; //keccak256("CancelOrder(bytes32 orderHash)") bytes32 internal constant _EIP712_CANCEL_ORDER_SCHEMA_HASH = 0xe70fd60b1c6c2a2394fdccb638d1e84b9233a8fa520436c8cf500b6d5b62cd64; struct Order { address user; //address of the Order Creator making the sale address sellToken; // address of the Token the Order Creator wants to sell address buyToken; // address of the Token the Order Creator wants to receive in return uint256 sellAmount; // amount of Token that the Order Creator wants to sell uint256 buyAmount; // amount of Token that the Order Creator wants to receive in return uint256 expirationTimeSeconds; //time after which the order is no longer valid } struct CancelOrder { bytes32 orderHash; } struct OrderInfo { bytes32 orderHash; // EIP712 typed data hash of the order (see LibOrder.getTypedDataHash). uint256 orderSellFilledAmount; // Amount of order that has already been filled. } // https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct function getOrderHash(Order memory order) internal pure returns (bytes32 orderHash) { orderHash = keccak256( abi.encode(_EIP712_ORDER_SCHEMA_HASH, order.user, order.sellToken, order.buyToken, order.sellAmount, order.buyAmount, order.expirationTimeSeconds) ); } // https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct function getCancelOrderHash(bytes32 orderHash) internal pure returns (bytes32 cancelOrderHash) { cancelOrderHash = keccak256( abi.encode(_EIP712_CANCEL_ORDER_SCHEMA_HASH, orderHash) ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/cryptography/EIP712.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. * * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding * they need in their contracts using a combination of `abi.encode` and `keccak256`. * * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA * ({_hashTypedDataV4}). * * The implementation of the domain separator was designed to be as efficient as possible while still properly updating * the chain id to protect against replay attacks on an eventual fork of the chain. * * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. * * _Available since v3.4._ */ abstract contract EIP712 { /* solhint-disable var-name-mixedcase */ // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to // invalidate the cached domain separator if the chain id changes. bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; uint256 private immutable _CACHED_CHAIN_ID; address private immutable _CACHED_THIS; bytes32 private immutable _HASHED_NAME; bytes32 private immutable _HASHED_VERSION; bytes32 private immutable _TYPE_HASH; /* solhint-enable var-name-mixedcase */ /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ constructor(string memory name, string memory version) { bytes32 hashedName = keccak256(bytes(name)); bytes32 hashedVersion = keccak256(bytes(version)); bytes32 typeHash = keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ); _HASHED_NAME = hashedName; _HASHED_VERSION = hashedVersion; _CACHED_CHAIN_ID = block.chainid; _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); _CACHED_THIS = address(this); _TYPE_HASH = typeHash; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { return _CACHED_DOMAIN_SEPARATOR; } else { return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); } } function _buildDomainSeparator( bytes32 typeHash, bytes32 nameHash, bytes32 versionHash ) private view returns (bytes32) { return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/cryptography/SignatureChecker.sol) pragma solidity ^0.8.0; import "./ECDSA.sol"; import "../Address.sol"; import "../../interfaces/IERC1271.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * _Available since v4.1._ */ library SignatureChecker { /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature); if (error == ECDSA.RecoverError.NoError && recovered == signer) { return true; } (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature) ); return (success && result.length == 32 && abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0-rc.2) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @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 */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"address","name":"fee_address","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"maker","type":"address"},{"indexed":false,"internalType":"address","name":"taker","type":"address"},{"indexed":false,"internalType":"address","name":"makerSellToken","type":"address"},{"indexed":false,"internalType":"address","name":"takerSellToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"makerSellAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"takerSellAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"makerVolumeFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"takerVolumeFee","type":"uint256"}],"name":"Swap","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"}],"name":"cancelOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"cancelSignature","type":"bytes"}],"name":"cancelOrderWithSig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cancelled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"makerOrder","type":"tuple"},{"internalType":"bytes","name":"makerSignature","type":"bytes"},{"internalType":"uint256","name":"fillAmount","type":"uint256"},{"internalType":"bool","name":"fillAvailable","type":"bool"}],"name":"fillOrder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"filled","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"}],"name":"getOpenOrder","outputs":[{"components":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"internalType":"uint256","name":"orderSellFilledAmount","type":"uint256"}],"internalType":"struct LibOrder.OrderInfo","name":"orderInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidCancelSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"order","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidOrderSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"makerOrder","type":"tuple"},{"components":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"sellToken","type":"address"},{"internalType":"address","name":"buyToken","type":"address"},{"internalType":"uint256","name":"sellAmount","type":"uint256"},{"internalType":"uint256","name":"buyAmount","type":"uint256"},{"internalType":"uint256","name":"expirationTimeSeconds","type":"uint256"}],"internalType":"struct LibOrder.Order","name":"takerOrder","type":"tuple"},{"internalType":"bytes","name":"makerSignature","type":"bytes"},{"internalType":"bytes","name":"takerSignature","type":"bytes"}],"name":"matchOrders","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taker_fee_numerator","type":"uint256"},{"internalType":"uint256","name":"_taker_fee_denominator","type":"uint256"},{"internalType":"uint256","name":"_maker_fee_numerator","type":"uint256"},{"internalType":"uint256","name":"_maker_fee_denominator","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040526000600355612710600455600580556127106006553480156200002757600080fd5b50604051620030083803806200300883398181016040528101906200004d919062000389565b828260008280519060200120905060008280519060200120905060007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90508260e081815250508161010081815250504660a08181525050620000b88184846200014b60201b60201c565b608081815250503073ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1681525050806101208181525050505050505080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505050620004c7565b60008383834630604051602001620001689594939291906200046a565b6040516020818303038152906040528051906020012090509392505050565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620001f082620001a5565b810181811067ffffffffffffffff82111715620002125762000211620001b6565b5b80604052505050565b60006200022762000187565b9050620002358282620001e5565b919050565b600067ffffffffffffffff821115620002585762000257620001b6565b5b6200026382620001a5565b9050602081019050919050565b60005b838110156200029057808201518184015260208101905062000273565b83811115620002a0576000848401525b50505050565b6000620002bd620002b7846200023a565b6200021b565b905082815260208101848484011115620002dc57620002db620001a0565b5b620002e984828562000270565b509392505050565b600082601f8301126200030957620003086200019b565b5b81516200031b848260208601620002a6565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620003518262000324565b9050919050565b620003638162000344565b81146200036f57600080fd5b50565b600081519050620003838162000358565b92915050565b600080600060608486031215620003a557620003a462000191565b5b600084015167ffffffffffffffff811115620003c657620003c562000196565b5b620003d486828701620002f1565b935050602084015167ffffffffffffffff811115620003f857620003f762000196565b5b6200040686828701620002f1565b9250506040620004198682870162000372565b9150509250925092565b6000819050919050565b620004388162000423565b82525050565b6000819050919050565b62000453816200043e565b82525050565b620004648162000344565b82525050565b600060a0820190506200048160008301886200042d565b6200049060208301876200042d565b6200049f60408301866200042d565b620004ae606083018562000448565b620004bd608083018462000459565b9695505050505050565b60805160a05160c05160e0516101005161012051612af16200051760003960006115a8015260006115ea015260006115c9015260006114fe015260006115540152600061157d0152612af16000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c8063acdf571811610066578063acdf57181461017f578063c50e7b6e146101af578063c8e93eca146101cb578063cb66394c146101fb578063dbb86c0f146102175761009e565b806314a59183146100a35780631e9c8a6c146100d3578063288cdc91146101035780632ac12622146101335780636fcba37714610163575b600080fd5b6100bd60048036038101906100b89190611a66565b610247565b6040516100ca9190611b23565b60405180910390f35b6100ed60048036038101906100e89190611b3e565b61077b565b6040516100fa9190611bc2565b60405180910390f35b61011d60048036038101906101189190611c09565b6108b0565b60405161012a9190611c45565b60405180910390f35b61014d60048036038101906101489190611c09565b6108c8565b60405161015a9190611b23565b60405180910390f35b61017d60048036038101906101789190611c60565b6108e8565b005b61019960048036038101906101949190611cc7565b61099a565b6040516101a69190611b23565b60405180910390f35b6101c960048036038101906101c49190611b3e565b6109c0565b005b6101e560048036038101906101e09190611d4f565b610ac6565b6040516101f29190611b23565b60405180910390f35b61021560048036038101906102109190611cc7565b610e07565b005b610231600480360381019061022c9190611cc7565b610ef8565b60405161023e9190611b23565b60405180910390f35b6000846040015173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff16146102bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102b690611e31565b60405180910390fd5b846020015173ffffffffffffffffffffffffffffffffffffffff16846040015173ffffffffffffffffffffffffffffffffffffffff1614610335576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161032c90611e31565b60405180910390fd5b846000015173ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614156103ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a390611e9d565b60405180910390fd5b60006103b78661077b565b905060006103c48661077b565b90506103d98660000151826000015186610f2c565b610418576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040f90611f09565b60405180910390fd5b61042b8760000151836000015187610f2c565b61046a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046190611f75565b60405180910390fd5b8560800151876080015161047e9190611fc4565b866060015188606001516104929190611fc4565b10156104d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ca9061206a565b60405180910390fd5b6000826020015188606001516104e9919061208a565b9050600082602001518860600151610501919061208a565b9050600089606001518a608001518461051a9190611fc4565b61052491906120ed565b9050600080838310610559578b608001518c60600151856105459190611fc4565b61054f91906120ed565b9150839050610560565b8491508290505b808b6020015173ffffffffffffffffffffffffffffffffffffffff166370a082318d600001516040518263ffffffff1660e01b81526004016105a2919061212d565b602060405180830381865afa1580156105bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105e3919061215d565b1015610624576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061b906121d6565b60405180910390fd5b818c6020015173ffffffffffffffffffffffffffffffffffffffff166370a082318e600001516040518263ffffffff1660e01b8152600401610666919061212d565b602060405180830381865afa158015610683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a7919061215d565b10156106e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106df90612242565b60405180910390fd5b816000806106f58f610f4f565b815260200190815260200160002060008282546107129190612262565b92505081905550806000806107268e610f4f565b815260200190815260200160002060008282546107439190612262565b925050819055506107688c600001518c600001518e602001518e602001518686610fc6565b6001975050505050505050949350505050565b6107836117b6565b61078c82610f4f565b816000018181525050600080826000015181526020019081526020016000205481602001818152505081606001518160200151106107ff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f690612304565b60405180910390fd5b8160a00151421115610846576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161083d90612370565b60405180910390fd5b600160008260000151815260200190815260200160002060009054906101000a900460ff16156108ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108a2906123dc565b60405180910390fd5b919050565b60006020528060005260406000206000915090505481565b60016020528060005260406000206000915054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610978576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161096f90612448565b60405180910390fd5b8360058190555082600681905550816003819055508060048190555050505050565b6000806109a684610f4f565b90506109b784600001518285610f2c565b91505092915050565b806000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a29906124b4565b60405180910390fd5b6000610a3d82610f4f565b905081606001516000808381526020019081526020016000205410610a97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8e90612520565b60405180910390fd5b600180600083815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000846000015173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610b3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3290611e9d565b60405180910390fd5b6000610b468661077b565b9050610b5b8660000151826000015187610f2c565b610b9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b9190611f75565b60405180910390fd5b600081602001518760600151610bb0919061208a565b9050838015610bbe57508481105b15610bc7578094505b80851115610c0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c01906125b2565b60405180910390fd5b60008760600151886080015187610c219190611fc4565b610c2b91906120ed565b905080886040015173ffffffffffffffffffffffffffffffffffffffff166370a08231336040518263ffffffff1660e01b8152600401610c6b919061212d565b602060405180830381865afa158015610c88573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cac919061215d565b1015610ced576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ce4906121d6565b60405180910390fd5b85886020015173ffffffffffffffffffffffffffffffffffffffff166370a082318a600001516040518263ffffffff1660e01b8152600401610d2f919061212d565b602060405180830381865afa158015610d4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d70919061215d565b1015610db1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da890612242565b60405180910390fd5b85600080856000015181526020019081526020016000206000828254610dd79190612262565b92505081905550610df88860000151338a602001518b604001518a86610fc6565b60019350505050949350505050565b6000610e1283610f4f565b905082606001516000808381526020019081526020016000205410610e6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6390612520565b60405180910390fd5b6000610e77826112c5565b9050610e8884600001518285610f2c565b610ec7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ebe9061261e565b60405180910390fd5b600180600084815260200190815260200160002060006101000a81548160ff02191690831515021790555050505050565b600080610f0484610f4f565b90506000610f11826112c5565b9050610f2285600001518286610f2c565b9250505092915050565b600080610f388461131a565b9050610f45858285611334565b9150509392505050565b60007f68d868c8698fc31da3a36bb7a184a4af099797794701bae97bea3de7ebe6e39960001b826000015183602001518460400151856060015186608001518760a00151604051602001610fa9979695949392919061264d565b604051602081830303815290604052805190602001209050919050565b600060065460055484610fd99190611fc4565b610fe391906120ed565b9050600060045460035484610ff89190611fc4565b61100291906120ed565b905060008211156110b1578573ffffffffffffffffffffffffffffffffffffffff166323b872dd89600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518463ffffffff1660e01b815260040161106c939291906126bc565b6020604051808303816000875af115801561108b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110af9190612708565b505b600081111561115e578473ffffffffffffffffffffffffffffffffffffffff166323b872dd88600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518463ffffffff1660e01b8152600401611119939291906126bc565b6020604051808303816000875af1158015611138573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115c9190612708565b505b8473ffffffffffffffffffffffffffffffffffffffff166323b872dd888a8487611188919061208a565b6040518463ffffffff1660e01b81526004016111a6939291906126bc565b6020604051808303816000875af11580156111c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e99190612708565b508573ffffffffffffffffffffffffffffffffffffffff166323b872dd89898588611214919061208a565b6040518463ffffffff1660e01b8152600401611232939291906126bc565b6020604051808303816000875af1158015611251573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112759190612708565b507f6950339c7661cca450281e53722525cc136590e622b011d5be7e4c4993685a6c88888888888887896040516112b3989796959493929190612735565b60405180910390a15050505050505050565b60007fe70fd60b1c6c2a2394fdccb638d1e84b9233a8fa520436c8cf500b6d5b62cd6460001b826040516020016112fd9291906127b3565b604051602081830303815290604052805190602001209050919050565b600061132d6113276114fa565b83611614565b9050919050565b60008060006113438585611647565b915091506000600481111561135b5761135a6127dc565b5b81600481111561136e5761136d6127dc565b5b1480156113a657508573ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16145b156113b6576001925050506114f3565b6000808773ffffffffffffffffffffffffffffffffffffffff16631626ba7e60e01b88886040516024016113eb929190612893565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161145591906128ff565b600060405180830381855afa9150503d8060008114611490576040519150601f19603f3d011682016040523d82523d6000602084013e611495565b606091505b50915091508180156114a8575060208151145b80156114ec5750631626ba7e60e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916818060200190518101906114ea919061292b565b145b9450505050505b9392505050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163073ffffffffffffffffffffffffffffffffffffffff1614801561157657507f000000000000000000000000000000000000000000000000000000000000000046145b156115a3577f00000000000000000000000000000000000000000000000000000000000000009050611611565b61160e7f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611699565b90505b90565b600082826040516020016116299291906129d0565b60405160208183030381529060405280519060200120905092915050565b6000806041835114156116895760008060006020860151925060408601519150606086015160001a905061167d878285856116d3565b94509450505050611692565b60006002915091505b9250929050565b600083838346306040516020016116b4959493929190612a07565b6040516020818303038152906040528051906020012090509392505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08360001c111561170e5760006003915091506117ad565b6000600187878787604051600081526020016040526040516117339493929190612a76565b6020604051602081039080840390855afa158015611755573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117a4576000600192509250506117ad565b80600092509250505b94509492505050565b604051806040016040528060008019168152602001600081525090565b6000604051905090565b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611835826117ec565b810181811067ffffffffffffffff82111715611854576118536117fd565b5b80604052505050565b60006118676117d3565b9050611873828261182c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006118a382611878565b9050919050565b6118b381611898565b81146118be57600080fd5b50565b6000813590506118d0816118aa565b92915050565b6000819050919050565b6118e9816118d6565b81146118f457600080fd5b50565b600081359050611906816118e0565b92915050565b600060c08284031215611922576119216117e7565b5b61192c60c061185d565b9050600061193c848285016118c1565b6000830152506020611950848285016118c1565b6020830152506040611964848285016118c1565b6040830152506060611978848285016118f7565b606083015250608061198c848285016118f7565b60808301525060a06119a0848285016118f7565b60a08301525092915050565b600080fd5b600080fd5b600067ffffffffffffffff8211156119d1576119d06117fd565b5b6119da826117ec565b9050602081019050919050565b82818337600083830152505050565b6000611a09611a04846119b6565b61185d565b905082815260208101848484011115611a2557611a246119b1565b5b611a308482856119e7565b509392505050565b600082601f830112611a4d57611a4c6119ac565b5b8135611a5d8482602086016119f6565b91505092915050565b6000806000806101c08587031215611a8157611a806117dd565b5b6000611a8f8782880161190c565b94505060c0611aa08782880161190c565b93505061018085013567ffffffffffffffff811115611ac257611ac16117e2565b5b611ace87828801611a38565b9250506101a085013567ffffffffffffffff811115611af057611aef6117e2565b5b611afc87828801611a38565b91505092959194509250565b60008115159050919050565b611b1d81611b08565b82525050565b6000602082019050611b386000830184611b14565b92915050565b600060c08284031215611b5457611b536117dd565b5b6000611b628482850161190c565b91505092915050565b6000819050919050565b611b7e81611b6b565b82525050565b611b8d816118d6565b82525050565b604082016000820151611ba96000850182611b75565b506020820151611bbc6020850182611b84565b50505050565b6000604082019050611bd76000830184611b93565b92915050565b611be681611b6b565b8114611bf157600080fd5b50565b600081359050611c0381611bdd565b92915050565b600060208284031215611c1f57611c1e6117dd565b5b6000611c2d84828501611bf4565b91505092915050565b611c3f816118d6565b82525050565b6000602082019050611c5a6000830184611c36565b92915050565b60008060008060808587031215611c7a57611c796117dd565b5b6000611c88878288016118f7565b9450506020611c99878288016118f7565b9350506040611caa878288016118f7565b9250506060611cbb878288016118f7565b91505092959194509250565b60008060e08385031215611cde57611cdd6117dd565b5b6000611cec8582860161190c565b92505060c083013567ffffffffffffffff811115611d0d57611d0c6117e2565b5b611d1985828601611a38565b9150509250929050565b611d2c81611b08565b8114611d3757600080fd5b50565b600081359050611d4981611d23565b92915050565b6000806000806101208587031215611d6a57611d696117dd565b5b6000611d788782880161190c565b94505060c085013567ffffffffffffffff811115611d9957611d986117e2565b5b611da587828801611a38565b93505060e0611db6878288016118f7565b925050610100611dc887828801611d3a565b91505092959194509250565b600082825260208201905092915050565b7f6d69736d61746368656420746f6b656e73000000000000000000000000000000600082015250565b6000611e1b601183611dd4565b9150611e2682611de5565b602082019050919050565b60006020820190508181036000830152611e4a81611e0e565b9050919050565b7f73656c662073776170206e6f7420616c6c6f7765640000000000000000000000600082015250565b6000611e87601583611dd4565b9150611e9282611e51565b602082019050919050565b60006020820190508181036000830152611eb681611e7a565b9050919050565b7f696e76616c69642074616b6572207369676e6174757265000000000000000000600082015250565b6000611ef3601783611dd4565b9150611efe82611ebd565b602082019050919050565b60006020820190508181036000830152611f2281611ee6565b9050919050565b7f696e76616c6964206d616b6572207369676e6174757265000000000000000000600082015250565b6000611f5f601783611dd4565b9150611f6a82611f29565b602082019050919050565b60006020820190508181036000830152611f8e81611f52565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611fcf826118d6565b9150611fda836118d6565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561201357612012611f95565b5b828202905092915050565b7f6f7264657273206e6f742063726f737365640000000000000000000000000000600082015250565b6000612054601283611dd4565b915061205f8261201e565b602082019050919050565b6000602082019050818103600083015261208381612047565b9050919050565b6000612095826118d6565b91506120a0836118d6565b9250828210156120b3576120b2611f95565b5b828203905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006120f8826118d6565b9150612103836118d6565b925082612113576121126120be565b5b828204905092915050565b61212781611898565b82525050565b6000602082019050612142600083018461211e565b92915050565b600081519050612157816118e0565b92915050565b600060208284031215612173576121726117dd565b5b600061218184828501612148565b91505092915050565b7f74616b6572206f72646572206e6f7420656e6f7567682062616c616e63650000600082015250565b60006121c0601e83611dd4565b91506121cb8261218a565b602082019050919050565b600060208201905081810360008301526121ef816121b3565b9050919050565b7f6d616b6572206f72646572206e6f7420656e6f7567682062616c616e63650000600082015250565b600061222c601e83611dd4565b9150612237826121f6565b602082019050919050565b6000602082019050818103600083015261225b8161221f565b9050919050565b600061226d826118d6565b9150612278836118d6565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156122ad576122ac611f95565b5b828201905092915050565b7f6f726465722069732066696c6c65640000000000000000000000000000000000600082015250565b60006122ee600f83611dd4565b91506122f9826122b8565b602082019050919050565b6000602082019050818103600083015261231d816122e1565b9050919050565b7f6f72646572206578706972656400000000000000000000000000000000000000600082015250565b600061235a600d83611dd4565b915061236582612324565b602082019050919050565b600060208201905081810360008301526123898161234d565b9050919050565b7f6f726465722063616e63656c6564000000000000000000000000000000000000600082015250565b60006123c6600e83611dd4565b91506123d182612390565b602082019050919050565b600060208201905081810360008301526123f5816123b9565b9050919050565b7f6f6e6c79206665652061646472657373206d6179207570646174652066656573600082015250565b6000612432602083611dd4565b915061243d826123fc565b602082019050919050565b6000602082019050818103600083015261246181612425565b9050919050565b7f6f6e6c792075736572206d61792063616e63656c206f72646572000000000000600082015250565b600061249e601a83611dd4565b91506124a982612468565b602082019050919050565b600060208201905081810360008301526124cd81612491565b9050919050565b7f6f7264657220616c72656164792066696c6c6564000000000000000000000000600082015250565b600061250a601483611dd4565b9150612515826124d4565b602082019050919050565b60006020820190508181036000830152612539816124fd565b9050919050565b7f66696c6c20616d6f756e74206578636565647320617661696c61626c6520736960008201527f7a65000000000000000000000000000000000000000000000000000000000000602082015250565b600061259c602283611dd4565b91506125a782612540565b604082019050919050565b600060208201905081810360008301526125cb8161258f565b9050919050565b7f696e76616c69642063616e63656c207369676e61747572650000000000000000600082015250565b6000612608601883611dd4565b9150612613826125d2565b602082019050919050565b60006020820190508181036000830152612637816125fb565b9050919050565b61264781611b6b565b82525050565b600060e082019050612662600083018a61263e565b61266f602083018961211e565b61267c604083018861211e565b612689606083018761211e565b6126966080830186611c36565b6126a360a0830185611c36565b6126b060c0830184611c36565b98975050505050505050565b60006060820190506126d1600083018661211e565b6126de602083018561211e565b6126eb6040830184611c36565b949350505050565b60008151905061270281611d23565b92915050565b60006020828403121561271e5761271d6117dd565b5b600061272c848285016126f3565b91505092915050565b60006101008201905061274b600083018b61211e565b612758602083018a61211e565b612765604083018961211e565b612772606083018861211e565b61277f6080830187611c36565b61278c60a0830186611c36565b61279960c0830185611c36565b6127a660e0830184611c36565b9998505050505050505050565b60006040820190506127c8600083018561263e565b6127d5602083018461263e565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600081519050919050565b600082825260208201905092915050565b60005b8381101561284557808201518184015260208101905061282a565b83811115612854576000848401525b50505050565b60006128658261280b565b61286f8185612816565b935061287f818560208601612827565b612888816117ec565b840191505092915050565b60006040820190506128a8600083018561263e565b81810360208301526128ba818461285a565b90509392505050565b600081905092915050565b60006128d98261280b565b6128e381856128c3565b93506128f3818560208601612827565b80840191505092915050565b600061290b82846128ce565b915081905092915050565b60008151905061292581611bdd565b92915050565b600060208284031215612941576129406117dd565b5b600061294f84828501612916565b91505092915050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b6000612999600283612958565b91506129a482612963565b600282019050919050565b6000819050919050565b6129ca6129c582611b6b565b6129af565b82525050565b60006129db8261298c565b91506129e782856129b9565b6020820191506129f782846129b9565b6020820191508190509392505050565b600060a082019050612a1c600083018861263e565b612a29602083018761263e565b612a36604083018661263e565b612a436060830185611c36565b612a50608083018461211e565b9695505050505050565b600060ff82169050919050565b612a7081612a5a565b82525050565b6000608082019050612a8b600083018761263e565b612a986020830186612a67565b612aa5604083018561263e565b612ab2606083018461263e565b9594505050505056fea2646970667358221220fb55cb008cf62628d048f407e2f32e5b4af461a4299941f16832b5fea33f4c1064736f6c634300080a0033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000f4bba1e2a5024a2754225b981e9a0db7d2c33ee900000000000000000000000000000000000000000000000000000000000000065a69675a616700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003322e310000000000000000000000000000000000000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000f4bba1e2a5024a2754225b981e9a0db7d2c33ee900000000000000000000000000000000000000000000000000000000000000065a69675a616700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003322e310000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name (string): ZigZag
Arg [1] : version (string): 2.1
Arg [2] : fee_address (address): 0xf4bba1e2a5024a2754225b981e9a0db7d2c33ee9
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 000000000000000000000000f4bba1e2a5024a2754225b981e9a0db7d2c33ee9
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000006
Arg [4] : 5a69675a61670000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 322e310000000000000000000000000000000000000000000000000000000000
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.