Address Contract Verified
Address
0x3638A3e2dfB3948597AD18B5dadeb0282501bBEd
Balance
0 ETH
Nonce
1
Code Size
2858 bytes
Creator
0x376d6db7...E9CD at tx 0x21103c13...f3c126
Indexed Transactions
0 (1 on-chain, 0% indexed)
Contract Bytecode
2858 bytes
0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80638cfa83e51161005b5780638cfa83e5146100ec578063a165527814610103578063a778adde14610118578063b13ca5f71461012b57600080fd5b80634ab37a711461008257806385fba364146100975780638a72ea6a146100aa575b600080fd5b610095610090366004610999565b61016a565b005b6100956100a53660046109bb565b6103d4565b6100bd6100b83660046109ee565b610609565b604080516001600160a01b03909416845261ffff92831660208501529116908201526060015b60405180910390f35b6100f561138881565b6040519081526020016100e3565b61010b610640565b6040516100e39190610a07565b6100956101263660046109bb565b6106bb565b6101527f000000000000000000000000d3607bc8c7927b348bac50dc224c28e3ce933ca681565b6040516001600160a01b0390911681526020016100e3565b7f000000000000000000000000d3607bc8c7927b348bac50dc224c28e3ce933ca660008061ffff841661138981106101a4576101a4610a64565b6040805160608101825292909101546001600160a01b03811680845261ffff600160a01b830481166020860152600160b01b90920490911691830191909152909150331480159061026d575080516040516331a9108f60e11b815261ffff851660048201526001600160a01b0391821691841690636352211e90602401602060405180830381865afa15801561023e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102629190610a7a565b6001600160a01b0316145b80156102e75750805160405163e985e9c560e01b81526001600160a01b0391821660048201523060248201529083169063e985e9c590604401602060405180830381865afa1580156102c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102e79190610aa3565b801561037e5750604081015161ffff16158061037e575060408181015190516331a9108f60e11b815261ffff909116600482015233906001600160a01b03841690636352211e90602401602060405180830381865afa15801561034e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103729190610a7a565b6001600160a01b031614155b1561039b576040516282b42960e81b815260040160405180910390fd5b600080845560405161ffff85169133917f899cab278284ae4a91172caa0943607a0bcb19766254c3ebe1139be00650b1029190a3505050565b7f000000000000000000000000d3607bc8c7927b348bac50dc224c28e3ce933ca660008061ffff8516611389811061040e5761040e610a64565b6040805160608101825292909101546001600160a01b03811680845261ffff600160a01b830481166020860152600160b01b909204909116918301919091529091501580610462575061046084610884565b155b15610480576040516305995b5360e41b815260040160405180910390fd5b604081015161ffff16158015906104a35750806040015161ffff168361ffff1614155b156104c15760405163e4989c3d60e01b815260040160405180910390fd5b6104ca83610884565b6104e75760405163166b6e5960e01b815260040160405180910390fd5b8261ffff168461ffff167f19e358413b77c4e90878dfd18da749fa4208a97d4bbd4598d699d6ba1b57fa7060405160405180910390a36000845580516040516323b872dd60e01b81523360048201526001600160a01b03918216602482015261ffff85166044820152908316906323b872dd90606401600060405180830381600087803b15801561057757600080fd5b505af115801561058b573d6000803e3d6000fd5b5050825160208401516040516323b872dd60e01b81526001600160a01b03928316600482015233602482015261ffff909116604482015290851692506323b872dd9150606401600060405180830381600087803b1580156105eb57600080fd5b505af11580156105ff573d6000803e3d6000fd5b5050505050505050565b600081611389811061061a57600080fd5b01546001600160a01b038116915061ffff600160a01b8204811691600160b01b90041683565b610648610940565b60408051620271208101909152600061138981835b828210156106b25760408051606081018252838601546001600160a01b038116825261ffff600160a01b82048116602080850191909152600160b01b909204169282019290925282526001909201910161065d565b50505050905090565b7f000000000000000000000000d3607bc8c7927b348bac50dc224c28e3ce933ca66106e583610884565b1580610705575061ffff821615801590610705575061070382610884565b155b156107235760405163166b6e5960e01b815260040160405180910390fd5b6040516331a9108f60e11b815261ffff8416600482015233906001600160a01b03831690636352211e90602401602060405180830381865afa15801561076d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107919190610a7a565b6001600160a01b0316146107b7576040516282b42960e81b815260040160405180910390fd5b6040518060600160405280336001600160a01b031681526020018461ffff1681526020018361ffff1681525060008461ffff1661138981106107fb576107fb610a64565b825191018054602084015160409485015161ffff908116600160b01b0261ffff60b01b19928216600160a01b026001600160b01b03199094166001600160a01b0390961695909517929092171692909217905590518382169185169033907fe899a6e29fab942958a400b4db4c5dec136446a7966a69e0011735027a33fff390600090a4505050565b60405161ffff821660248201526000906001600160a01b037f000000000000000000000000d3607bc8c7927b348bac50dc224c28e3ce933ca6169060440160408051601f198184030181529181526020820180516001600160e01b03166331a9108f60e11b179052516108f79190610ac5565b600060405180830381855afa9150503d8060008114610932576040519150601f19603f3d011682016040523d82523d6000602084013e610937565b606091505b50909392505050565b60405180620271200160405280611389905b60408051606081018252600080825260208083018290529282015282526000199092019101816109525790505090565b803561ffff8116811461099457600080fd5b919050565b6000602082840312156109ab57600080fd5b6109b482610982565b9392505050565b600080604083850312156109ce57600080fd5b6109d783610982565b91506109e560208401610982565b90509250929050565b600060208284031215610a0057600080fd5b5035919050565b620753608101818360005b611389811015610a5b57815180516001600160a01b0316845260208082015161ffff90811682870152604092830151169185019190915260609093019290910190600101610a12565b50505092915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610a8c57600080fd5b81516001600160a01b03811681146109b457600080fd5b600060208284031215610ab557600080fd5b815180151581146109b457600080fd5b6000825160005b81811015610ae65760208186018101518583015201610acc565b50600092019182525091905056fea2646970667358221220678679a7db9bb77c812fcae7781b11a0c068743fdacf8d5e934a1e214859989964736f6c63430008100033
Verified Source Code Full Match
Compiler: v0.8.16+commit.07a7930e
EVM: london
Optimization: Yes (200 runs)
NononSwap.sol 130 lines
// SPDX-License-Identifier: MIT
/// @title nonon swap
pragma solidity 0.8.16;
import "./interfaces/INonon.sol";
// errors
error Unauthorized();
error OfferForNonexistentToken();
error NoActiveOffer();
error NotRequestedToken();
error TokenHasExistingOffer();
// state
struct TokenOffer {
address owner;
uint16 ownedId;
uint16 wantedId; // unset (zero) is considered to be open
}
contract NononSwap {
uint256 public constant nononMaxSupply = 5000;
address public immutable nononAddress;
// events
event OfferCreated(address indexed owner, uint256 indexed ownedId, uint256 indexed wantedId);
event OfferCancelled(address indexed owner, uint256 indexed ownedId);
event SwapCompleted(uint256 indexed firstTokenId, uint256 indexed secondTokenId);
/**
* @dev Mapping (implemented as an array for gas efficiency) between token
* ids and token offers. Thus, `offers[0]` should never be defined.
*/
TokenOffer[nononMaxSupply + 1] public offers;
constructor(address _nononAddress) {
nononAddress = _nononAddress;
}
/**
* @dev Create a token swap offer for the owned token `_ownedId` and the
* wanted token `_wantedId`. It can also be used to update already set
* offers so the owner doenst need to call `removeOffer` every time they
* want to change their offer.
* @param _ownedId Token that `msg.sender` owns and wants to swap for
* `_wantedId`
* @param _wantedId Token that `msg.sender` wants, 0 if they dont care
* and just want to farm friendship points.
*/
function createTokenOffer(uint16 _ownedId, uint16 _wantedId) external {
INonon nonon = INonon(nononAddress);
if (!nononExists(_ownedId) || (_wantedId != 0 && !nononExists(_wantedId))) {
revert OfferForNonexistentToken();
}
if (nonon.ownerOf(_ownedId) != msg.sender) {
revert Unauthorized();
}
offers[_ownedId] = TokenOffer({owner: msg.sender, ownedId: _ownedId, wantedId: _wantedId});
emit OfferCreated(msg.sender, _ownedId, _wantedId);
}
function completeTokenOffer(uint16 _offerTokenId, uint16 _swapId) external {
INonon nonon = INonon(nononAddress);
TokenOffer memory offer = offers[_offerTokenId];
if (offer.owner == address(0) || !nononExists(_offerTokenId)) {
revert NoActiveOffer();
}
if (offer.wantedId != 0 && _swapId != offer.wantedId) {
revert NotRequestedToken();
}
if (!nononExists(_swapId)) {
revert OfferForNonexistentToken();
}
emit SwapCompleted(_offerTokenId, _swapId);
assembly {
sstore(add(offers.slot, _offerTokenId), 0)
}
// transfer tokens
nonon.transferFrom(msg.sender, offer.owner, _swapId);
nonon.transferFrom(offer.owner, msg.sender, offer.ownedId);
}
function removeOffer(uint16 _tokenId) external {
INonon nonon = INonon(nononAddress);
TokenOffer memory offer = offers[_tokenId];
// allow removal (aka: dont revert) in one of these cases:
// - the user is the creator of the offer OR
// - the offer creator no longer owns the offer token OR
// - the swap contract does not have approval to transfer nonons on behalf of owner OR
// - msg.sender is the owner of offer.wantedId
// if none of these conditions are met (inverses are all true), revert
if (
offer.owner != msg.sender // User is not the creator of the offer
&& nonon.ownerOf(_tokenId) == offer.owner // Offer creator still owns the token
&& nonon.isApprovedForAll(offer.owner, address(this)) // Contract is approved
&& (offer.wantedId == 0 || nonon.ownerOf(offer.wantedId) != msg.sender) // No wantedId or user does not own the wantedId
) {
revert Unauthorized();
}
assembly {
sstore(add(offers.slot, _tokenId), 0)
}
emit OfferCancelled(msg.sender, _tokenId);
}
function nononExists(uint16 tokenId) internal view returns (bool success) {
(success,) = nononAddress.staticcall(abi.encodeWithSignature("ownerOf(uint256)", tokenId));
}
function getAllOffers() external view returns (TokenOffer[nononMaxSupply + 1] memory) {
return offers;
}
}
INonon.sol 9 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.16;
import "ERC721A/IERC721A.sol";
interface INonon is IERC721A {
function exists(uint256 _tokenId) external view returns (bool);
}
IERC721A.sol 282 lines
// SPDX-License-Identifier: MIT
// ERC721A Contracts v4.2.3
// Creator: Chiru Labs
pragma solidity ^0.8.4;
/**
* @dev Interface of ERC721A.
*/
interface IERC721A {
/**
* The caller must own the token or be an approved operator.
*/
error ApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/
error ApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/
error BalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/
error MintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/
error MintZeroQuantity();
/**
* The token does not exist.
*/
error OwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/
error TransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/
error TransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/
error TransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/
error TransferToZeroAddress();
/**
* The token does not exist.
*/
error URIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/
error MintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/
error OwnershipNotInitializedForExtraData();
// =============================================================
// STRUCTS
// =============================================================
struct TokenOwnership {
// The address of the owner.
address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.
uint64 startTimestamp;
// Whether the token has been burned.
bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.
uint24 extraData;
}
// =============================================================
// TOKEN COUNTERS
// =============================================================
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/
function totalSupply() external view returns (uint256);
// =============================================================
// IERC165
// =============================================================
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
// =============================================================
// IERC721
// =============================================================
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external payable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external payable;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external payable;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
// =============================================================
// IERC721Metadata
// =============================================================
/**
* @dev Returns the token collection name.
*/
function name() external view returns (string memory);
/**
* @dev Returns the token collection symbol.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/
function tokenURI(uint256 tokenId) external view returns (string memory);
// =============================================================
// IERC2309
// =============================================================
/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/
event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);
}
Read Contract
getAllOffers 0xa1655278 → tuple[5001]
nononAddress 0xb13ca5f7 → address
nononMaxSupply 0x8cfa83e5 → uint256
offers 0x8a72ea6a → address, uint16, uint16
Write Contract 3 functions
These functions modify contract state and require a wallet transaction to execute.
completeTokenOffer 0x85fba364
uint16 _offerTokenId
uint16 _swapId
createTokenOffer 0xa778adde
uint16 _ownedId
uint16 _wantedId
removeOffer 0x4ab37a71
uint16 _tokenId
Recent Transactions
This address has 1 on-chain transactions, but only 0% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →