> 文档中心 > Solidity实践-一个简单的盲盒合约

Solidity实践-一个简单的盲盒合约

数组操作库,用于删除数组元素,返回一个新数组

// SPDX-License-Identifier: MITpragma solidity >=0.8.0;library ArrayUtil {    //根据值获取元素在数组中的索引    function getIdx(uint[] memory arr, uint val) internal pure returns(uint) { uint index = type(uint).max; for (uint i; i = array.length){     return array; } if(array.length <= 1){     return new uint[](0); } uint _len = array.length - 1; uint[] memory newArray = new uint[](_len); for(uint n; n < newArray.length; n++){     if(n < index){  newArray[n] = array[n];     }else{  newArray[n] = array[n + 1];     } } return newArray;    }    // 根据值从数组中删除对应元素    function removeValue(uint[] memory array, uint value) internal pure returns (uint[] memory) { uint idx = getIdx(array, value); return removeAtIndex(array, idx);    }}

盲盒合约

// SPDX-License-Identifier: MITpragma solidity >=0.8.0;import "@openzeppelin/contracts/utils/Address.sol";import "@openzeppelin/contracts/utils/math/SafeMath.sol";import "@openzeppelin/contracts/token/ERC20/IERC20.sol";import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";import "./library/ArrayUtil.sol";contract BlindBox {    using SafeMath for uint;    using Address for address;    using SafeERC20 for IERC20;    address public factory;    uint private _rand = 1;    address private feeTo; // 购买盲盒的费用接收地址    address private settleToken; // 结算token    // 记录盲盒中的token以及剩余总量    struct ShardStore { address token; uint256 amount;    }    mapping(uint256 => ShardStore) public shardStore;    // 记录盲盒不同id盒子每次发放的数量    mapping(uint256 => uint256) public rewardAmount; // 每次发放数量 idx => amount    uint256 public price; // 盲盒价格    event Buy(uint256, uint256);    constructor() { factory = msg.sender;    }    // 生成指定范围随机数    function _getRandom(uint256 _start, uint256 _end) private returns(uint256) { if(_start == _end){     return _start; } uint256 _length = _end - _start; uint256 random = uint256(keccak256(abi.encodePacked(block.difficulty, block.timestamp, _rand))); random = random % _length + _start; _rand++; return random;    }    // 购买盲盒    function buy() external virtual returns(uint256 shardId){ require(settleToken != address(0), 'Tips: 0001'); require(feeTo != address(0), 'Tips: 0003'); // 生成1-100的随机数 uint256 rd = _getRandom(0, 100); // 74%机率买到0号盒子 if(rd >= 98 && rd = 92 && rd = 74 && rd 0 require(rewardAmount[shardId] > 0, 'Tips: 0004'); // 验证价格>0 require(price > 0, 'Tips: 0002'); // 验证盒子中token数量>发放数量 require(_shardStore.amount >= rewardAmount[shardId], 'Tips: 0001'); // 支付到feeTo uint256 amount = price; IERC20(settleToken).safeTransferFrom(msg.sender, feeTo, amount); // 发放盲盒token IERC20(_shardStore.token).safeTransfer(msg.sender, rewardAmount[shardId]); // 盒子中剩余token数量-发放数量 shardStore[shardId].amount -= rewardAmount[shardId]; emit Buy(shardId, rewardAmount[shardId]);    }    // 往盒子中放入token,shardId的值为 0-3    function addShard(uint256 shardId, address token, uint256 amount) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0008'); require(shardStore[shardId].amount == 0, 'Tip: 0001'); IERC20(token).safeTransferFrom(msg.sender, address(this), amount); shardStore[shardId] = ShardStore(token, amount); return true;    }    // 撤出盒子中剩余的token    function removeShard(uint256 shardId) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0008'); if(shardStore[shardId].amount > 0){     IERC20(shardStore[shardId].token).safeTransfer(msg.sender, shardStore[shardId].amount); } delete shardStore[shardId]; return true;    }    // 设置费用接收地址feeTo    function setFeeTo(address _feeTo) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0008'); feeTo = _feeTo; return true;    }    // 设置结算token    function setSettleToken(address _settleToken) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0009'); settleToken = _settleToken; return true;    }    // 设置盲盒价格和不同盒子每次发放数量    function setPrice(uint256 _price, uint256 _idx, uint256 _rewardAmount) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0009'); price = _price; rewardAmount[_idx] = _rewardAmount; return true;    }    // 重置发放数量为0    function removeRewardAmount(uint256 _idx) external virtual returns(bool){ require(msg.sender == factory, 'Tips: 0009'); delete rewardAmount[_idx]; return true;    }}