文件 1 的 6:AccessControl.sol
pragma solidity ^0.8.0;
import "Context.sol";
import "ERC165.sol";
interface IAccessControl {
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping (address => bool) members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId
|| super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override {
require(hasRole(getRoleAdmin(role), _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, getRoleAdmin(role), adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 6:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
this;
return msg.data;
}
}
文件 3 的 6:CryptoCatsMarketV2.sol
pragma solidity ^0.8.0;
import "AccessControl.sol";
import "SafeMath.sol";
import "Context.sol";
import "ERC165.sol";
import "IERC165.sol";
interface CryptoCats{
function catIndexToAddress(uint catIndex) external view returns(address);
function buyCat(uint catIndex) external payable;
function transfer(address addressto, uint catIndex) external;
}
contract CryptoCatsMarketV2 is AccessControl {
using SafeMath for uint256;
string public name = "CryptoCatsMarketV2";
CryptoCats public constant cryptocats = CryptoCats(0x19c320b43744254ebdBcb1F1BD0e2a3dc08E01dc);
uint public FEE = 20;
uint public feesToCollect = 0;
struct Bid {
uint catIndex;
uint amount;
address bidder;
}
mapping (uint => Bid) public bids;
mapping (address => uint) public pendingWithdrawals;
event CryptoCatsTransfer(uint indexed index, address from, address to);
event CryptoCatsBidCreated(uint indexed index, uint amount, address bidder);
event CryptoCatsBidWithdrawn(uint indexed index, uint amount, address bidder);
event CryptoCatsBought(uint indexed index, uint amount, address seller, address bidder);
constructor() public {
_setupRole(DEFAULT_ADMIN_ROLE, 0xaaEa1B588c41dddEa4afDa5105e1C4f0bdB017F5);
}
function collectFees() public {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));
uint amount = feesToCollect;
feesToCollect = 0;
payable(0xaaEa1B588c41dddEa4afDa5105e1C4f0bdB017F5).transfer(amount);
}
function changeFee(uint newFee) public {
require(hasRole(DEFAULT_ADMIN_ROLE, msg.sender));
FEE = newFee;
}
function bid(uint catIndex) public payable {
require(msg.value > 0, "BID::Value is 0");
Bid memory bid = bids[catIndex];
require(msg.value > bid.amount, "BID::New bid too low");
pendingWithdrawals[bid.bidder] += bid.amount;
bids[catIndex] = Bid(catIndex, msg.value, msg.sender);
emit CryptoCatsBidCreated(catIndex, msg.value, msg.sender);
}
function withdrawBid(uint catIndex) public {
Bid memory bid = bids[catIndex];
require(msg.sender == bid.bidder, "WITHDRAW_BID::Only bidder can withdraw his bid");
emit CryptoCatsBidWithdrawn(catIndex, bid.amount, msg.sender);
uint amount = bid.amount;
bids[catIndex] = Bid(catIndex, 0, address(0x0));
payable(msg.sender).transfer(amount);
}
function acceptBid(uint catIndex, uint minPrice) public {
require(cryptocats.catIndexToAddress(catIndex) == msg.sender, "ACCEPT_BID::Only owner can accept bid");
Bid memory bid = bids[catIndex];
require(bid.amount > 0, "ACCEPT_BID::Bid amount is 0");
require(bid.amount >= minPrice, "ACCEPT_BID::Min price not respected");
cryptocats.buyCat(catIndex);
cryptocats.transfer(bid.bidder, catIndex);
uint fees = bid.amount.div(FEE);
feesToCollect += fees;
uint amount = bid.amount.sub(fees);
bids[catIndex] = Bid(catIndex, 0, address(0x0));
pendingWithdrawals[msg.sender] += amount;
emit CryptoCatsBought(catIndex, amount, msg.sender, bid.bidder);
emit CryptoCatsTransfer(catIndex, msg.sender, bid.bidder);
}
function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
pendingWithdrawals[msg.sender] = 0;
payable(msg.sender).transfer(amount);
}
}
文件 4 的 6:ERC165.sol
pragma solidity ^0.8.0;
import "IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 6:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 6 的 6:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
{
"compilationTarget": {
"CryptoCatsMarketV2.sol": "CryptoCatsMarketV2"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"bidder","type":"address"}],"name":"CryptoCatsBidCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"bidder","type":"address"}],"name":"CryptoCatsBidWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"bidder","type":"address"}],"name":"CryptoCatsBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"CryptoCatsTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"catIndex","type":"uint256"},{"internalType":"uint256","name":"minPrice","type":"uint256"}],"name":"acceptBid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"catIndex","type":"uint256"}],"name":"bid","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"bids","outputs":[{"internalType":"uint256","name":"catIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"bidder","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"changeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cryptocats","outputs":[{"internalType":"contract CryptoCats","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feesToCollect","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pendingWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"catIndex","type":"uint256"}],"name":"withdrawBid","outputs":[],"stateMutability":"nonpayable","type":"function"}]