Created
December 13, 2021 22:04
-
-
Save z0r0z/82f0c075d368bcc0962b3abc7f476cd3 to your computer and use it in GitHub Desktop.
Escrow for NFT and ERC20 using IERC20
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: GPL-3.0-or-later | |
| pragma solidity >=0.8.0; | |
| /// @notice Standard ERC-20 token interface with EIP-2612 {permit} extension. | |
| interface IERC20 { | |
| /// @dev ERC-20: | |
| function allowance(address owner, address spender) external view returns (uint256); | |
| function balanceOf(address account) external view returns (uint256); | |
| function totalSupply() external view returns (uint256); | |
| function approve(address spender, uint256 amount) external returns (bool); | |
| function transfer(address to, uint256 amount) external returns (bool); | |
| function transferFrom(address from, address to, uint256 amount) external returns (bool); | |
| event Approval(address indexed owner, address indexed spender, uint256 amount); | |
| event Transfer(address indexed from, address indexed to, uint256 amount); | |
| /// @dev EIP-2612: | |
| function permit(address owner, address spender, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external; | |
| } | |
| /// @notice Simple bilateral escrow for ETH and ERC-20/721 tokens. | |
| contract Escrow { | |
| uint256 public escrowCount; | |
| mapping(uint256 => Escrow) public escrows; | |
| event Deposit( | |
| bool nft, | |
| address indexed depositor, | |
| address indexed receiver, | |
| IERC20 token, | |
| uint256 amount, | |
| uint256 indexed registration, | |
| string details); | |
| event Release(uint256 indexed registration); | |
| struct Escrow { | |
| bool nft; | |
| address depositor; | |
| address receiver; | |
| IERC20 token; | |
| uint256 value; | |
| } | |
| /// @notice Deposits ETH/ERC-20 into escrow. | |
| /// @param receiver The account that receives funds. | |
| /// @param token The asset used for funds. | |
| /// @param value The amount of funds. | |
| /// @param details Describes context of escrow - stamped into event. | |
| function deposit(address receiver, IERC20 token, uint256 value, string memory details) payable public virtual { | |
| if (address(token) == address(0)) { | |
| require(msg.value == value, "WRONG_MSG_VALUE"); | |
| } else { | |
| token.transferFrom(msg.sender, address(this), value); | |
| } | |
| /// @dev Increment registered escrows and assign # to escrow deposit. | |
| unchecked { | |
| escrowCount++; | |
| } | |
| uint256 registration = escrowCount; | |
| escrows[registration] = Escrow(false, msg.sender, receiver, token, value); | |
| emit Deposit(false, msg.sender, receiver, token, value, registration, details); | |
| } | |
| /// @notice Deposits ERC-721 into escrow. | |
| /// @param receiver The account that receives `tokenId`. | |
| /// @param token The NFT asset. | |
| /// @param tokenId The NFT `tokenId`. | |
| /// @param details Describes context of escrow - stamped into event. | |
| function depositNFT(address receiver, IERC20 token, uint256 tokenId, string memory details) public virtual { | |
| token.transferFrom(msg.sender, address(this), tokenId); | |
| /// @dev Increment registered escrows and assign # to escrow deposit. | |
| unchecked { | |
| escrowCount++; | |
| } | |
| uint256 registration = escrowCount; | |
| escrows[registration] = Escrow(true, msg.sender, receiver, token, tokenId); | |
| emit Deposit(true, msg.sender, receiver, token, tokenId, registration, details); | |
| } | |
| /// @notice Releases escrowed assets to designated `receiver`. | |
| /// @param registration The index of escrow deposit. | |
| function release(uint256 registration) public virtual { | |
| Escrow storage escrow = escrows[registration]; | |
| require(msg.sender == escrow.depositor, "NOT_DEPOSITOR"); | |
| require(!escrow.nft, "NFT"); | |
| if (address(escrow.token) == address(0)) { | |
| (bool success, ) = escrow.receiver.call{value: escrow.value}(""); | |
| require(success, "ETH_TRANSFER_FAILED"); | |
| } else { | |
| escrow.token.transfer(escrow.receiver, escrow.value); | |
| } | |
| emit Release(registration); | |
| } | |
| /// @notice Releases escrowed NFT `tokenId` to designated `receiver`. | |
| /// @param registration The index of escrow deposit. | |
| function releaseNFT(uint256 registration) public virtual { | |
| Escrow storage escrow = escrows[registration]; | |
| require(msg.sender == escrow.depositor, "NOT_DEPOSITOR"); | |
| require(escrow.nft, "NOT_NFT"); | |
| escrow.token.transferFrom(address(this), escrow.receiver, escrow.value); | |
| emit Release(registration); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment