私はいくつかの特定のルールでランダム カードを生成するスマート コントラクトに取り組んでいます。Chainlink VRF を使用して乱数を生成し、そのようなコントラクトを実装しようとしていました。
//SPDX-License-Identifier: Unlicense
pragma solidity >=0.7.4;
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "../utils/Context.sol";
import "../utils/ReentrancyGuard.sol";
import "../utils/Address.sol";
import "../NFT/CardNFTAccessControls.sol";
import "../NFT/CardNFT.sol";
/**
* @notice Factory contract for NFT handling payments on mint
*/
contract NFTFactory is Context, ReentrancyGuard, VRFConsumerBase {
// using SafeMath for uint256;
using Address for address payable;
struct CardInfo {
uint256 num;
uint256 kind;
uint256 value;
uint256 qty;
}
struct NFTInfo {
uint256 edition;
uint256 cardInfoId;
}
struct RequestNFTConfig {
uint256 limit;
bool kind;
uint256 id;
}
event NFTCreated(
uint256 id,
uint256 num,
uint256 kind,
uint256 edition
);
event RandomReturned(
bytes32 requestId,
uint256 randomness
);
/// @notice chainlink rng request value mapping
mapping(bytes32 => RequestNFTConfig) private requestIds;
/// @notice edition number id
uint256 private editionId;
/// @notice for switching off factory functionality
bool public isPaused;
/// @notice responsible for enforcing mint and admin role
CardNFTAccessControls accessControls;
/// @notice NFT contract
CardNFT cardNFT;
/// @notice platform fee recipient address which will accept all fees and mint price
address payable platformFeeRecipient;
/// @notice keyhash for chainlink rng generator
bytes32 internal keyHash;
/// @notice fee for chainlink rng generator
uint256 internal rngFee;
/// @notice rng generator result
uint256 public randomResult;
/// @notice deck card information for calculation
mapping(uint256 => CardInfo) deckInfo;
/// @notice nft array
mapping(uint256 => NFTInfo) nfts;
modifier whenNotPaused() {
require(!isPaused, "Function is currently paused");
_;
}
constructor(
CardNFTAccessControls _accessControls,
CardNFT _cardNFT,
address payable _platformFeeRecipient
) VRFConsumerBase(
0xa555fC018435bef5A13C6c6870a9d4C11DEC329C,
0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06
) {
require(address(_accessControls) != address(0), "NFTFactory: Invalid Access Controls");
require(address(_cardNFT) != address(0), "NFTFactory: Invalid NFT");
require(_platformFeeRecipient != address(0), "NFTFactory: Invalid platform Fee recipient");
accessControls = _accessControls;
cardNFT = _cardNFT;
platformFeeRecipient = _platformFeeRecipient;
keyHash = 0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186;
rngFee = 0.1 * 10 ** 18; // 0.1 LINK
}
/**
@notice create one NFT
@param _limit min or maximum number of card
@param _kind limit kind with lower or higher
@param _price price of NFT mint
@param _amount amount of NFTs to mint
@param _data additional data to leave
*/
function create(uint256 _limit, bool _kind, uint256 _price, uint256 _amount, bytes memory _data) external payable nonReentrant whenNotPaused {
require(_msgSender().isContract() == false, "Factory.create: No contracts are permitted");
require(_msgSender() != address(0), "Factory.create: sender address is ZERO");
uint256 buyPrice = msg.value;
require(buyPrice >= _price, "Factory.create: payment should be same to original price");
// (bool platformTransferSuccess,) = platformFeeRecipient.call{value : buyPrice}("");
// require(platformTransferSuccess, "Factory.mintPayment: Failed to send platform fee");
address creator = _msgSender();
if(_amount > 1) {
uint256[] memory _ids = cardNFT.batchMint(creator, _amount, _data);
require(_amount == _ids.length, "Factory.create: should batch mint same amount of nfts");
for(uint256 i=0; i<_ids.length; i++) {
getRandomNumber(_ids[i], _limit, _kind);
}
} else {
uint256 id = cardNFT.mint(creator, _data);
getRandomNumber(id, _limit, _kind);
}
}
/**
@notice generate actual NFT info
@param _requestId request id for chainlink rng
@param _randomness random number which return from chainlink org
*/
function generateNFTInfo(bytes32 _requestId, uint256 _randomness) private {
RequestNFTConfig storage config = requestIds[_requestId];
uint256 total = getTotalQtyToNumber(config.limit);
bool _kind = config.kind;
uint256 rngResult = 0;
if(_kind) {
rngResult = _randomness * (200000 - total) + total;
} else {
rngResult = _randomness * total;
}
uint256 cardInfoId = getNearestQtyCard(rngResult);
NFTInfo storage nft = nfts[config.id];
uint256 edition = _getNextEditionID();
_incrementEditionId();
nft.edition = edition;
nft.cardInfoId = cardInfoId;
CardInfo storage cardInfo = deckInfo[cardInfoId];
emit NFTCreated(config.id, cardInfo.num, cardInfo.kind, edition);
}
/**
* Requests randomness
*/
function getRandomNumber(uint256 _id, uint256 _limit, bool _kind) private {
require(LINK.balanceOf(address(this)) >= rngFee, "Not enough LINK - fill contract with faucet");
bytes32 requestId = requestRandomness(keyHash, rngFee);
RequestNFTConfig storage config = requestIds[requestId];
config.id = _id;
config.kind = _kind;
config.limit = _limit;
}
/**
* Callback function used by VRF Coordinator
*/
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
emit RandomReturned(requestId, randomness);
generateNFTInfo(requestId, randomness);
}
......
}
BSC テストネットでこれを試しましたが、RandomReturnedイベント ログはなく、generateNFTInfo 関数による更新もありませんでした。また、ローカルに chainlink-node をインストールせずに、ローカルで単体テストをテストする方法がわかりません。誰でもこれで私を助けることができますか?