Skip to content

Instantly share code, notes, and snippets.

@thekillertoaster
Created March 29, 2023 19:11
Show Gist options
  • Select an option

  • Save thekillertoaster/c55d439dd1c05c22705830077eaa3ca7 to your computer and use it in GitHub Desktop.

Select an option

Save thekillertoaster/c55d439dd1c05c22705830077eaa3ca7 to your computer and use it in GitHub Desktop.
Enabling the safe swapping of different NFTs between users. Requires setApprovalForAll to be ran on involved Token Contracts
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract ERC721TokenSwap is ReentrancyGuard {
event SwapCreated(uint256 indexed swapId, address indexed trader1, address indexed trader2);
event SwapExecuted(uint256 indexed swapId);
struct Swap {
address trader1;
address trader2;
address[] trader1TokenAddresses;
uint256[] trader1TokenIds;
address[] trader2TokenAddresses;
uint256[] trader2TokenIds;
bool trader1Approval;
bool trader2Approval;
}
Swap[] public swaps;
function createSwap(
address _trader2,
address[] memory _trader1TokenAddresses,
uint256[] memory _trader1TokenIds,
address[] memory _trader2TokenAddresses,
uint256[] memory _trader2TokenIds
) external returns (uint256) {
require(_trader1TokenIds.length > 0 && _trader2TokenIds.length > 0, "Both traders must have tokens to trade");
require(_trader1TokenAddresses.length == _trader1TokenIds.length, "Token addresses and IDs must match for trader1");
require(_trader2TokenAddresses.length == _trader2TokenIds.length, "Token addresses and IDs must match for trader2");
for (uint256 i = 0; i < _trader1TokenIds.length; i++) {
require(IERC721(_trader1TokenAddresses[i]).ownerOf(_trader1TokenIds[i]) == msg.sender, "Trader1 does not own token");
}
for (uint256 i = 0; i < _trader2TokenIds.length; i++) {
require(IERC721(_trader2TokenAddresses[i]).ownerOf(_trader2TokenIds[i]) == _trader2, "Trader2 does not own token");
}
uint256 swapId = swaps.length;
swaps.push(Swap(msg.sender, _trader2, _trader1TokenAddresses, _trader1TokenIds, _trader2TokenAddresses, _trader2TokenIds, false, false));
emit SwapCreated(swapId, msg.sender, _trader2);
return swapId;
}
function approveSwap(uint256 _swapId) external nonReentrant {
Swap storage swap = swaps[_swapId];
require(msg.sender == swap.trader1 || msg.sender == swap.trader2, "Not a participant");
require(swap.trader1 != address(0) && swap.trader2 != address(0), "Invalid traders");
if (msg.sender == swap.trader1) {
swap.trader1Approval = true;
} else if (msg.sender == swap.trader2) {
swap.trader2Approval = true;
}
if (swap.trader1Approval && swap.trader2Approval) {
executeSwap(_swapId);
}
}
function executeSwap(uint256 _swapId) private {
Swap storage swap = swaps[_swapId];
for (uint256 i = 0; i < swap.trader1TokenIds.length; i++) {
IERC721(swap.trader1TokenAddresses[i]).safeTransferFrom(
swap.trader1,
swap.trader2,
swap.trader1TokenIds[i]
);
}
for (uint256 i = 0; i < swap.trader2TokenIds.length; i++) {
IERC721(swap.trader2TokenAddresses[i]).safeTransferFrom(
swap.trader2,
swap.trader1,
swap.trader2TokenIds[i]
);
}
emit SwapExecuted(_swapId);
delete swaps[_swapId];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment