Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Payment contract #2

Open
wants to merge 3 commits into
base: feature/jakepyo/contract
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions contracts/AINFT721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,10 @@ contract AINFT721 is
super._requireMinted(tokenId);
}

function _isApprovedOrOwner(
function isApprovedOrOwner(
address spender,
uint256 tokenId
) internal view virtual override(ERC721) returns (bool)
) public view virtual returns (bool)
{
return super._isApprovedOrOwner(spender, tokenId);
}
Expand Down Expand Up @@ -194,7 +194,7 @@ contract AINFT721 is
string memory newTokenURI
) external returns (bool) {
require(
(_isApprovedOrOwner(_msgSender(), tokenId) ||
(isApprovedOrOwner(_msgSender(), tokenId) ||
hasRole(DEFAULT_ADMIN_ROLE, _msgSender())),
"AINFT721::updateTokenURI() - not owner of tokenId or contract owner"
);
Expand Down
8 changes: 8 additions & 0 deletions contracts/AINFT721Upgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ contract AINFT721Upgradeable is
{
return super._isApprovedOrOwner(spender, tokenId);
}

function isApprovedOrOwner(
address spender,
uint256 tokenId
) public view virtual returns (bool)
{
return _isApprovedOrOwner(spender, tokenId);
}


////
Expand Down
88 changes: 88 additions & 0 deletions contracts/AINPayment.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

import "./interfaces/IAINFT.sol";

contract AINPayment is Ownable, ReentrancyGuard {
IERC20 public _ain;
IAINFT public _ainft;

uint256[2] public _price; // [update_price, rollback_price]

constructor(address ainft, address ain) {
require(ain == 0x3A810ff7211b40c4fA76205a14efe161615d0385, "AINPayment: only supports AIN ERC20");
_ain = IERC20(ain);
_ainft = IAINFT(ainft);
_price = [0, 0];
}

function setPrice(uint256[2] calldata price) external onlyOwner {
require(!(_price[0] == price[0] && _price[1] == price[1]), "AINPayment::setPrice, the new price is same as the old one.");
_price[0] = price[0];
_price[1] = price[1];
}

function pay(uint256 amount) public nonReentrant returns(bool) {
require(amount > 0, "Amount must be greater than 0");
require(_ain.balanceOf(_msgSender()) >= amount, "Insufficient balance");

bool success = _ain.transfer(address(this), amount);
return success;
}

function executeUpdate(uint256 tokenId, string memory newTokenURI) external returns(bool) {
require(_ainft.isApprovedOrOwner(_msgSender(), tokenId), "AINPayment::executeUpdate, owner of AINFT or holder only call this");
require(pay(_price[0]), "Insufficient AIN");

bool success = _ainft.updateTokenURI(tokenId, newTokenURI);
return success;

}

function executeRollback(uint256 tokenId) external returns(bool) {
require(_ainft.isApprovedOrOwner(_msgSender(), tokenId), "AINPayment::executeRollback, owner of AINFT or holder only call this");
require(pay(_price[1]), "Insufficient AIN");

bool success = _ainft.rollbackTokenURI(tokenId);
return success;

}

function withdraw(uint256 amount) public onlyOwner nonReentrant returns(bool) {
require(owner() != address(0), "Owner should be set");
require(_ain.balanceOf(address(this)) >= amount, "Insufficient balance");

_ain.approve(owner(), amount);
require(_ain.allowance(address(this), owner()) >= amount, "Insufficient amount is allowed");
bool success = _ain.transferFrom(address(this), owner(), amount);
return success;
}

function withdrawAll() public onlyOwner nonReentrant returns(bool) {
require(owner() != address(0), "Owner should be set");

uint256 stackedAin = _ain.balanceOf(address(this));
_ain.approve(owner(), stackedAin);
require(_ain.allowance(address(this), owner()) >= stackedAin, "Insufficient amount is allowed");
bool success = _ain.transferFrom(address(this), owner(), stackedAin);
return success;
}

function destruct(string memory areYouSure) external payable onlyOwner {
require(owner() != address(0), "Owner should be set");
require(keccak256(abi.encodePacked(areYouSure)) == keccak256(abi.encodePacked("DELETE")), "Please type DELETE if you really want to destruct");

// 1. withdraw all AIN to owner
withdrawAll();

// 2. withdraw all ethers stored in this contract to owner
address payable _owner = payable(owner());
uint256 balance = address(this).balance;
require(balance > 0, "The contract has no funds to withdraw");
_owner.transfer(balance);
}
}
6 changes: 6 additions & 0 deletions contracts/interfaces/IAINFT.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;

// import "@openzeppelin/contracts/interfaces/IERC721Enumerable.sol";

//TODO: implement the function inside
interface IAINFT {

function isApprovedOrOwner(address spender, uint256 tokenId) external view returns (bool);
function tokenURICurrentVersion(uint256 tokenId) external view returns (uint256);
function setBaseURI(string memory newBaseURI) external returns (bool);

///@dev fetch the tokenURI of tokenId by certain version
function tokenURIByVersion(uint256 tokenId, uint256 uriVersion) external view returns (string memory);

Expand Down