Merge branch 'arbitrum' into pub_arb_one

This commit is contained in:
yuexin 2023-06-21 11:59:30 +08:00
commit b5caa46da1
12 changed files with 20162 additions and 14230 deletions

File diff suppressed because one or more lines are too long

View File

@ -3235,7 +3235,7 @@
}
},
"schemaVersion": "3.4.11",
"updatedAt": "2023-06-06T11:06:42.487Z",
"updatedAt": "2023-06-20T10:50:21.829Z",
"networkType": "ethereum",
"devdoc": {
"kind": "dev",

View File

@ -228,7 +228,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [],
@ -241,7 +242,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [],
@ -254,7 +256,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -291,7 +294,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -310,7 +314,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -329,7 +334,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -371,7 +377,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -395,7 +402,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -414,7 +422,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [],
@ -427,7 +436,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -446,7 +456,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -564,7 +575,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [],
@ -577,7 +589,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -596,7 +609,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -620,7 +634,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -639,7 +654,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [],
@ -652,7 +668,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -790,7 +807,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -822,7 +840,8 @@
}
],
"stateMutability": "view",
"type": "function"
"type": "function",
"constant": true
},
{
"inputs": [
@ -29587,10 +29606,206 @@
},
"networks": {
"421613": {
"events": {},
"events": {
"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "approved",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Approval",
"type": "event"
},
"0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "owner",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "operator",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "approved",
"type": "bool"
}
],
"name": "ApprovalForAll",
"type": "event"
},
"0x6fb12a9545315eb6982084f0c16aaa522d6073c42806eed44c5775ddd2682431": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256[]",
"name": "tokenIds",
"type": "uint256[]"
}
],
"name": "BatchMint",
"type": "event"
},
"0x57424d5909ad92dd80fbaa1967a047a5975a0e9bb94726d561734e667cdf4227": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Lock",
"type": "event"
},
"0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff": {
"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"
},
"0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d": {
"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"
},
"0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b": {
"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"
},
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
},
"0xa58a8ae4556605e0a8c4d993e8009ee9bea04a4bdfb3209a76ff8b83fa26b320": {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "UnLock",
"type": "event"
}
},
"links": {},
"address": "0x07Bad070e403a4Bad2Eec3BA3894c4524d3d2674",
"transactionHash": "0xd33e62a8012181146b4fd9d5def5b1666740ce6e2e9cc2f612e4791fb83dc372"
"address": "0xae37bb7BcA26Bab9a11D8BaE8fdB97f63b82c189",
"transactionHash": "0xaaac6bf3620a39f02ca5a28c6bf038ab943e0d5cce49f6da2f17ab90aa1202ab"
},
"1665974821170": {
"events": {},
@ -29600,7 +29815,8 @@
}
},
"schemaVersion": "3.4.11",
"updatedAt": "2023-06-08T05:33:25.988Z",
"updatedAt": "2023-06-20T10:50:21.824Z",
"networkType": "ethereum",
"devdoc": {
"kind": "dev",
"methods": {

View File

@ -5,112 +5,161 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../core/HasSignature.sol";
import "../interfaces/IBEERC721.sol";
import "../interfaces/IBEERC1155.sol";
import "../interfaces/IAsset.sol";
import "../utils/TimeChecker.sol";
import "../utils/UInt.sol";
import "./MallBase.sol";
contract BENftMall is MallBase, ReentrancyGuard, HasSignature, TimeChecker {
using SafeERC20 for IERC20;
using UInt for uint256;
constructor() HasSignature("NftMall", "1") {}
mapping(address => bool) public nftTokenSupported;
mapping(address => bool) public erc721Supported;
mapping(address => bool) public erc1155Supported;
// Events
event BuyTransaction(
address indexed buyer,
uint256 indexed nonce,
uint256 tokenId,
address[3] addresses,
uint256 price
uint256 indexed orderId,
address currency,
uint256 price,
address[] nftAddresses,
uint256[] ids,
uint256[] amounts
);
function addNFTTokenSupport(address nftToken) external onlyOwner {
nftTokenSupported[nftToken] = true;
}
event AddNFTSuppout(address nftToken);
event RemoveNFTSuppout(address nftToken);
function removeNFTTokenSupport(address nftToken) external onlyOwner {
nftTokenSupported[nftToken] = false;
}
function ignoreSignature(
address[4] calldata addresses,
uint256[] calldata signArray,
bytes calldata signature
) external signatureValid(signature) {
// address[4] [seller_address,nft_address,payment_token_address, buyer_address]
// uint256[4] [token_id,price,salt_nonce,startTime]
bytes32 criteriaMessageHash = getMessageHash(
addresses[1],
addresses[2],
addresses[3],
signArray
);
checkSigner(_msgSender(), criteriaMessageHash, signature);
_useSignature(signature);
/**
* @dev Add ERC20 support
*/
function addERC721Support(address nftToken) external onlyOwner {
erc721Supported[nftToken] = true;
emit AddNFTSuppout(nftToken);
}
/**
* @dev Function matched transaction with user signatures
* @dev Remove 721 NFT support
*/
function removeERC721Support(address nftToken) external onlyOwner {
erc721Supported[nftToken] = false;
emit RemoveNFTSuppout(nftToken);
}
/**
* @dev Add 1155 NFT support
*/
function addERC1155Support(address nftToken) external onlyOwner {
erc1155Supported[nftToken] = true;
emit AddNFTSuppout(nftToken);
}
/**
* @dev Remove 1155 NFT support
*/
function removeERC1155Support(address nftToken) external onlyOwner {
erc1155Supported[nftToken] = false;
emit RemoveNFTSuppout(nftToken);
}
/**
* @dev Buy NFT and other Game item from mall
*/
function buyNFT(
address[3] calldata addresses,
uint256[4] calldata values,
address currency,
address[] memory nftAddresses,
uint256[] memory ids,
uint256[] memory amounts,
uint256[] memory values, // [orderId, price, startTime, saltNonce]
bytes calldata signature
) external nonReentrant signatureValid(signature) timeValid(values[3]) {
// address[3] [seller_address,nft_address,payment_token_address]
// uint256[4] [token_id,price,salt_nonce,startTime]
// bytes seller_signature
require(nftTokenSupported[addresses[1]], "BENftMall: Unsupported NFT");
require(erc20Supported[addresses[2]], "BENftMall: invalid payment method");
address to = _msgSender();
) external nonReentrant signatureValid(signature) timeValid(values[2]) {
require(erc20Supported[currency], "BENftMall: invalid payment method");
require(values.length == 4, "BENftMall: invalid values length");
require(
nftAddresses.length == ids.length && ids.length == amounts.length,
"BENftMall: nftAddresses, ids and amounts length mismatch"
);
uint256[] memory signArray = new uint256[](values.length);
require(nftAddresses.length > 0, "BENftMall: ids length is zero");
for (uint256 i = 0; i < nftAddresses.length; ++i) {
require(
erc721Supported[nftAddresses[i]] || erc1155Supported[nftAddresses[i]],
"BENftMall: nft token is not supported"
);
}
uint256[] memory signArray = new uint256[](ids.length * 2 + 4);
for (uint256 i = 0; i < nftAddresses.length; ++i) {
signArray[i * 2] = ids[i];
signArray[i * 2 + 1] = amounts[i];
}
for (uint256 i = 0; i < values.length; ++i) {
signArray[i] = values[i];
signArray[ids.length * 2 + i] = values[i];
}
bytes32 criteriaMessageHash = getMessageHash(
addresses[1],
addresses[2],
to,
currency,
_msgSender(),
nftAddresses,
signArray
);
checkSigner(addresses[0], criteriaMessageHash, signature);
checkSigner(executor, criteriaMessageHash, signature);
// Check payment approval and buyer balance
IERC20 paymentContract = IERC20(addresses[2]);
require(
paymentContract.balanceOf(to) >= values[1],
IERC20(currency).balanceOf(_msgSender()) >= values[1],
"BENftMall: buyer doesn't have enough token to buy this item"
);
require(
paymentContract.allowance(to, address(this)) >= values[1],
"BENftMall: buyer doesn't approve marketplace to spend payment amount"
IERC20(currency).allowance(_msgSender(), address(this)) >= values[1],
"BENftMall: buyer doesn't approve enough token to buy this item"
);
paymentContract.safeTransferFrom(to, feeToAddress, values[1]);
// mint item to user
IBEERC721 nft = IBEERC721(addresses[1]);
nft.mint(to, values[0]);
// Transfer payment to seller
IERC20(currency).safeTransferFrom(_msgSender(), feeToAddress, values[1]);
for (uint256 i = 0; i < nftAddresses.length; ++i) {
if (erc721Supported[nftAddresses[i]]) {
IAsset(nftAddresses[i]).batchMint(
_msgSender(),
ids[i].asSingletonArray()
);
} else if (erc1155Supported[nftAddresses[i]]) {
IBEERC1155(nftAddresses[i]).mintBatch(
_msgSender(),
ids[i].asSingletonArray(),
amounts[i].asSingletonArray(),
""
);
}
}
_useSignature(signature);
// emit sale event
emit BuyTransaction(to, values[2], values[0], addresses, values[1]);
// emit buy event
emit BuyTransaction(
_msgSender(),
values[0],
currency,
values[1],
nftAddresses,
ids,
amounts
);
}
function getMessageHash(
address _nftAddress,
address _tokenAddress,
address _buyerAddress,
address[] memory _nftAddresses,
uint256[] memory _datas
) public pure returns (bytes32) {
bytes memory encoded = abi.encodePacked(
_nftAddress,
_tokenAddress,
_buyerAddress
);
uint256 len = _datas.length;
for (uint256 i = 0; i < len; ++i) {
bytes memory encoded = abi.encodePacked(_tokenAddress, _buyerAddress);
for (uint256 i = 0; i < _nftAddresses.length; i++) {
encoded = bytes.concat(encoded, abi.encodePacked(_nftAddresses[i]));
}
for (uint256 i = 0; i < _datas.length; ++i) {
encoded = bytes.concat(encoded, abi.encodePacked(_datas[i]));
}
return keccak256(encoded);

View File

@ -77,15 +77,15 @@ contract NFT is AccessControl, ERC721Enumerable {
/**
* @dev Add address for lock item
*/
function grantLockRole(address to) external {
function setLockRole(address to) external {
grantRole(LOCK_ROLE, to);
}
/**
* @dev Remove address for lock item
*/
function removeLockRole(address account) external {
revokeRole(LOCK_ROLE, account);
function removeLockRole(address to) external {
revokeRole(LOCK_ROLE, to);
}
/**

View File

@ -3,7 +3,6 @@ pragma solidity 0.8.10;
import "@openzeppelin/contracts/access/Ownable.sol";
contract TimeChecker is Ownable {
mapping(address => bool) private approvalLists;
uint256 private _duration;
constructor() {

View File

@ -88,22 +88,55 @@ module.exports = async function main(callback) {
// }
// }
const gameMarketInstance = await GameItemMarket.at(
cfgs.find((c) => c.name === "GameItemMarket").address
// const gameMarketInstance = await GameItemMarket.at(
// cfgs.find((c) => c.name === "GameItemMarket").address
// );
// if (gameMarketInstance) {
// await gameMarketInstance.setFeeToAddress(config.market.feeToAddress);
// console.log(
// `mall receive fee address set to : ${config.market.feeToAddress}`
// );
// await gameMarketInstance.updateExecutor(config.admins.admin);
// console.log(`mall executor set to : ${config.admins.admin}`);
// for (let token of config.market.paymentTokens) {
// await gameMarketInstance.addERC20Support(token);
// console.log(`add token for mall payment: ${token}`);
// }
// }
const nftMallInstance = await BENftMall.at(
cfgs.find((c) => c.name === "BENftMall").address
);
if (gameMarketInstance) {
await gameMarketInstance.setFeeToAddress(config.market.feeToAddress);
if (nftMallInstance) {
await nftMallInstance.setFeeToAddress(config.market.feeToAddress);
console.log(
`mall receive fee address set to : ${config.market.feeToAddress}`
`nft mall receive fee address set to : ${config.market.feeToAddress}`
);
await gameMarketInstance.updateExecutor(config.admins.admin);
await nftMallInstance.updateExecutor(config.admins.admin);
console.log(`mall executor set to : ${config.admins.admin}`);
for (let token of config.market.paymentTokens) {
await gameMarketInstance.addERC20Support(token);
await nftMallInstance.addERC20Support(token);
console.log(`add token for mall payment: ${token}`);
}
await nftMallInstance.addERC721Support(heroInstance.address);
console.log(`add token for mall sell: ${heroInstance.address}`);
await nftMallInstance.addERC721Support(equipInstance.address);
console.log(`add token for mall sell: ${equipInstance.address}`);
await nftMallInstance.addERC721Support(chipInstance.address);
console.log(`add token for mall sell: ${chipInstance.address}`);
await heroInstance.setMintRole(nftMallInstance.address);
await equipInstance.setMintRole(nftMallInstance.address);
await chipInstance.setMintRole(nftMallInstance.address);
const testHeroInstance = await NFT.at(
cfgs.find((c) => c.name === "TestHERO").address
);
await nftMallInstance.addERC721Support(testHeroInstance.address);
await testHeroInstance.setMintRole(nftMallInstance.address);
}
callback(0);

View File

@ -2,11 +2,7 @@ const config = require("../config/config");
const base = require("../scripts/base");
module.exports = async function (deployer, network, accounts) {
const tokens = [
{ name: "HERO", desc: "CRYPTO ELITE'S HERO", limit: 0 },
{ name: "WEAPON", desc: "CRYPTO ELITE'S WEAPON", limit: 0 },
{ name: "CHIP", desc: "CRYPTO ELITE'S CHIP", limit: 0 },
];
const tokens = [{ name: "HERO", desc: "CRYPTO ELITE'S HERO", limit: 0 }];
for (let i = 0, l = tokens.length; i < l; i++) {
const { name, desc, limit } = tokens[i];
let Nft = artifacts.require("tokens/erc721/NFT");

View File

@ -18,32 +18,32 @@ module.exports = async function (deployer, network, accounts) {
// network,
// });
// await deployer.deploy(BENftMall);
// const nftMallInstance = await BENftMall.deployed();
// if (nftMallInstance) {
// console.log("BENftMall successfully deployed.");
// }
// base.updateArray({
// name: "BENftMall",
// type: "logic",
// json: "assets/contracts/BENftMall.json",
// address: nftMallInstance.address,
// network,
// });
await deployer.deploy(GameItemMarket);
const gameMarketInstance = await GameItemMarket.deployed();
if (gameMarketInstance) {
console.log("GameItemMarket successfully deployed.");
await deployer.deploy(BENftMall);
const nftMallInstance = await BENftMall.deployed();
if (nftMallInstance) {
console.log("BENftMall successfully deployed.");
}
base.updateArray({
name: "GameItemMarket",
name: "BENftMall",
type: "logic",
json: "assets/contracts/GameItemMarket.json",
address: gameMarketInstance.address,
json: "assets/contracts/BENftMall.json",
address: nftMallInstance.address,
network,
});
// await deployer.deploy(GameItemMarket);
// const gameMarketInstance = await GameItemMarket.deployed();
// if (gameMarketInstance) {
// console.log("GameItemMarket successfully deployed.");
// }
// base.updateArray({
// name: "GameItemMarket",
// type: "logic",
// json: "assets/contracts/GameItemMarket.json",
// address: gameMarketInstance.address,
// network,
// });
// await deployer.deploy(GameItemMall);
// const gameMallInstance = await GameItemMall.deployed();
// if (gameMallInstance) {

View File

@ -69,7 +69,7 @@
"name": "BENftMall",
"type": "logic",
"json": "assets/contracts/BENftMall.json",
"address": "0x38Bf9f3C29D8384B6A79435745AE796cd2465545"
"address": "0x4d71dE0428328112A78D402A6fdd7ceD1C96B71e"
},
{
"name": "GameItemMarket",
@ -82,5 +82,11 @@
"type": "logic",
"json": "assets/contracts/GameItemMall.json",
"address": "0x1D058c7c7451c34BbfF9c0dF1C16b95C5d171d64"
},
{
"name": "TestHERO",
"type": "erc721",
"json": "assets/contracts/NFT.json",
"address": "0xae37bb7BcA26Bab9a11D8BaE8fdB97f63b82c189"
}
]

6
package-lock.json generated
View File

@ -19,7 +19,7 @@
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24",
"truffle": "^5.4.23",
"truffle-plugin-stdjsonin": "git+https://github.com/mhrsalehi/truffle-plugin-stdjsonin.git",
"truffle-plugin-stdjsonin": "github:mhrsalehi/truffle-plugin-stdjsonin",
"truffle-plugin-verify": "^0.5.25"
}
},
@ -20576,7 +20576,6 @@
"node_modules/truffle-plugin-stdjsonin": {
"version": "0.5.14",
"resolved": "git+ssh://git@github.com/mhrsalehi/truffle-plugin-stdjsonin.git#0ddb4110de7e14b2242f7467600d1ac149e2c460",
"integrity": "sha512-W2CIxNozYggLgNGXbPnFJX/xRaTUH2VfMV2bXGTizRwbc/W2dKVzkHVLBCArckter4Qkdj3IFZVVjmlabmasKA==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -41399,9 +41398,8 @@
},
"truffle-plugin-stdjsonin": {
"version": "git+ssh://git@github.com/mhrsalehi/truffle-plugin-stdjsonin.git#0ddb4110de7e14b2242f7467600d1ac149e2c460",
"integrity": "sha512-W2CIxNozYggLgNGXbPnFJX/xRaTUH2VfMV2bXGTizRwbc/W2dKVzkHVLBCArckter4Qkdj3IFZVVjmlabmasKA==",
"dev": true,
"from": "truffle-plugin-stdjsonin@git+https://github.com/mhrsalehi/truffle-plugin-stdjsonin.git",
"from": "truffle-plugin-stdjsonin@https://github.com/mhrsalehi/truffle-plugin-stdjsonin/",
"requires": {
"cli-logger": "^0.5.40"
}

View File

@ -30,7 +30,7 @@
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24",
"truffle": "^5.4.23",
"truffle-plugin-stdjsonin": "git+https://github.com/mhrsalehi/truffle-plugin-stdjsonin.git",
"truffle-plugin-stdjsonin": "github:mhrsalehi/truffle-plugin-stdjsonin",
"truffle-plugin-verify": "^0.5.25"
},
"dependencies": {