mirror of
https://github.com/supleed2/COMP70017-PoDL-T2.git
synced 2024-12-22 05:35:50 +00:00
Implement ERC721
This commit is contained in:
parent
1c93831b80
commit
134518387e
180
src/ERC721.sol
180
src/ERC721.sol
|
@ -1,66 +1,204 @@
|
||||||
// SPDX-License-Identifier: UNLICENSED
|
// SPDX-License-Identifier: UNLICENSED
|
||||||
pragma solidity ^0.8.17;
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "./libraries/StringUtils.sol";
|
||||||
import "./interfaces/IERC20.sol";
|
import "./interfaces/IERC20.sol";
|
||||||
import "./interfaces/IERC721.sol";
|
import "./interfaces/IERC721.sol";
|
||||||
|
|
||||||
contract ERC721 is IERC721Metadata {
|
contract ERC721 is IERC721Metadata {
|
||||||
|
mapping(uint256 => address) _approvals;
|
||||||
|
mapping(address => uint256) _balances;
|
||||||
|
mapping(address => mapping(address => bool)) _fullApprovals;
|
||||||
|
mapping(uint256 => address) _owners;
|
||||||
|
address _contractOwner;
|
||||||
|
string _name;
|
||||||
|
string _symbol;
|
||||||
|
string _baseUri;
|
||||||
|
IERC20 public _paymentToken;
|
||||||
|
uint256 _tokenPrice;
|
||||||
|
uint256 _totalSupply;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
string memory name,
|
string memory newName,
|
||||||
string memory symbol,
|
string memory newSymbol,
|
||||||
string memory baseUri,
|
string memory newBaseUri,
|
||||||
IERC20 paymentToken,
|
IERC20 newPaymentToken,
|
||||||
uint256 initialTokenPrice
|
uint256 newInitialTokenPrice
|
||||||
) {}
|
) {
|
||||||
|
_contractOwner = msg.sender;
|
||||||
|
_name = newName;
|
||||||
|
_symbol = newSymbol;
|
||||||
|
_baseUri = newBaseUri;
|
||||||
|
_paymentToken = newPaymentToken;
|
||||||
|
_tokenPrice = newInitialTokenPrice;
|
||||||
|
_totalSupply = 0;
|
||||||
|
}
|
||||||
|
|
||||||
function mint(address to) external {}
|
function mint(address to) external {
|
||||||
|
require(
|
||||||
|
_paymentToken.allowance(msg.sender, address(this)) >= _tokenPrice,
|
||||||
|
"insufficient allowance"
|
||||||
|
);
|
||||||
|
uint256 tokenId = _totalSupply + 1;
|
||||||
|
_totalSupply += tokenId;
|
||||||
|
_balances[to] += 1;
|
||||||
|
_owners[tokenId] = to;
|
||||||
|
_paymentToken.transferFrom(msg.sender, address(0), _tokenPrice);
|
||||||
|
emit Transfer(address(0), to, tokenId);
|
||||||
|
_tokenPrice += _tokenPrice / 10;
|
||||||
|
}
|
||||||
|
|
||||||
function balanceOf(address _owner) external view returns (uint256) {}
|
function balanceOf(address _owner) external view returns (uint256) {
|
||||||
|
return _balances[_owner];
|
||||||
|
}
|
||||||
|
|
||||||
function ownerOf(uint256 _tokenId) external view returns (address) {}
|
function ownerOf(uint256 _tokenId) external view returns (address) {
|
||||||
|
return _owners[_tokenId];
|
||||||
|
}
|
||||||
|
|
||||||
function transferFrom(
|
function transferFrom(
|
||||||
address _from,
|
address _from,
|
||||||
address _to,
|
address _to,
|
||||||
uint256 _tokenId
|
uint256 _tokenId
|
||||||
) external {}
|
) external {
|
||||||
|
require(_from == _owners[_tokenId]);
|
||||||
|
require(
|
||||||
|
msg.sender == _owners[_tokenId] ||
|
||||||
|
msg.sender == _approvals[_tokenId] ||
|
||||||
|
this.isApprovedForAll(_owners[_tokenId], msg.sender),
|
||||||
|
"not authorized"
|
||||||
|
);
|
||||||
|
_approvals[_tokenId] = address(0);
|
||||||
|
_balances[_from] -= 1;
|
||||||
|
_owners[_tokenId] = _to;
|
||||||
|
emit Transfer(_from, _to, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
function approve(address _approved, uint256 _tokenId) external {}
|
function approve(address _approved, uint256 _tokenId) external {
|
||||||
|
require(msg.sender == _owners[_tokenId], "not authorized");
|
||||||
|
_approvals[_tokenId] = _approved;
|
||||||
|
emit Approval(msg.sender, _approved, _tokenId);
|
||||||
|
}
|
||||||
|
|
||||||
function getApproved(uint256 _tokenId) external view returns (address) {}
|
function getApproved(uint256 _tokenId) external view returns (address) {
|
||||||
|
return _approvals[_tokenId];
|
||||||
|
}
|
||||||
|
|
||||||
function name() external view returns (string memory _name) {}
|
function name() external view returns (string memory) {
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
function symbol() external view returns (string memory _symbol) {}
|
function symbol() external view returns (string memory) {
|
||||||
|
return _symbol;
|
||||||
|
}
|
||||||
|
|
||||||
function tokenURI(uint256 _tokenId) external view returns (string memory) {}
|
function tokenURI(uint256 _tokenId) external view returns (string memory) {
|
||||||
|
return string.concat(_baseUri, StringUtils.toString(_tokenId));
|
||||||
|
}
|
||||||
|
|
||||||
// Bonus functions
|
// Bonus functions
|
||||||
|
|
||||||
function supportsInterface(bytes4 interfaceID)
|
function supportsInterface(bytes4 interfaceID)
|
||||||
external
|
external
|
||||||
view
|
pure
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{}
|
{
|
||||||
|
return interfaceID == 0x80ac58cd;
|
||||||
|
}
|
||||||
|
|
||||||
function safeTransferFrom(
|
function safeTransferFrom(
|
||||||
address _from,
|
address _from,
|
||||||
address _to,
|
address _to,
|
||||||
uint256 _tokenId,
|
uint256 _tokenId,
|
||||||
bytes memory data
|
bytes memory data
|
||||||
) external {}
|
) external {
|
||||||
|
require(
|
||||||
|
_from == _owners[_tokenId],
|
||||||
|
"_from does not own token _tokenId"
|
||||||
|
);
|
||||||
|
require(
|
||||||
|
msg.sender == _owners[_tokenId] ||
|
||||||
|
msg.sender == _approvals[_tokenId] ||
|
||||||
|
_fullApprovals[_owners[_tokenId]][msg.sender],
|
||||||
|
"not authorized"
|
||||||
|
);
|
||||||
|
require(_to != address(0), "can't send to 0x0");
|
||||||
|
require(_tokenId <= _totalSupply, "invalid tokenId");
|
||||||
|
_approvals[_tokenId] = address(0);
|
||||||
|
_balances[_from] -= 1;
|
||||||
|
_owners[_tokenId] = _to;
|
||||||
|
emit Transfer(_from, _to, _tokenId);
|
||||||
|
uint256 _toSize;
|
||||||
|
assembly {
|
||||||
|
_toSize := extcodesize(_to)
|
||||||
|
}
|
||||||
|
if (_toSize > 0) {
|
||||||
|
(, bytes memory result) = _to.staticcall(
|
||||||
|
abi.encodeWithSignature(
|
||||||
|
"onERC721Received(address,address,uint256,bytes)",
|
||||||
|
_from,
|
||||||
|
_to,
|
||||||
|
_tokenId,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (bytes4(result) != 0x150b7a02) {
|
||||||
|
revert("magic value not returned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function safeTransferFrom(
|
function safeTransferFrom(
|
||||||
address _from,
|
address _from,
|
||||||
address _to,
|
address _to,
|
||||||
uint256 _tokenId
|
uint256 _tokenId
|
||||||
) external {}
|
) external {
|
||||||
|
require(
|
||||||
|
_from == _owners[_tokenId],
|
||||||
|
"_from does not own token _tokenId"
|
||||||
|
);
|
||||||
|
require(
|
||||||
|
msg.sender == _owners[_tokenId] ||
|
||||||
|
msg.sender == _approvals[_tokenId] ||
|
||||||
|
_fullApprovals[_owners[_tokenId]][msg.sender],
|
||||||
|
"not authorized"
|
||||||
|
);
|
||||||
|
require(_to != address(0), "can't send to 0x0");
|
||||||
|
require(_tokenId <= _totalSupply, "invalid tokenId");
|
||||||
|
_approvals[_tokenId] = address(0);
|
||||||
|
_balances[_from] -= 1;
|
||||||
|
_owners[_tokenId] = _to;
|
||||||
|
emit Transfer(_from, _to, _tokenId);
|
||||||
|
uint256 _toSize;
|
||||||
|
assembly {
|
||||||
|
_toSize := extcodesize(_to)
|
||||||
|
}
|
||||||
|
if (_toSize > 0) {
|
||||||
|
(, bytes memory result) = _to.staticcall(
|
||||||
|
abi.encodeWithSignature(
|
||||||
|
"onERC721Received(address,address,uint256,bytes)",
|
||||||
|
_from,
|
||||||
|
_to,
|
||||||
|
_tokenId,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (bytes4(result) != 0x150b7a02) {
|
||||||
|
revert("magic value not returned");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setApprovalForAll(address _operator, bool _approved) external {}
|
function setApprovalForAll(address _operator, bool _approved) external {
|
||||||
|
_fullApprovals[msg.sender][_operator] = _approved;
|
||||||
|
emit ApprovalForAll(msg.sender, _operator, _approved);
|
||||||
|
}
|
||||||
|
|
||||||
function isApprovedForAll(address _owner, address _operator)
|
function isApprovedForAll(address _owner, address _operator)
|
||||||
external
|
external
|
||||||
view
|
view
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{}
|
{
|
||||||
|
return _fullApprovals[_owner][_operator];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue