编译器
0.8.18+commit.87f61d96
文件 1 的 4: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) {
return msg.data;
}
}
文件 2 的 4:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 3 的 4:PulseBitcoinLockNFTRewardsBulk.sol
pragma solidity ^0.8.9;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
interface PulseBitcoinLockNFTRewardsInterface {
function pulseBitcoinLockNftContractAddress() external view returns (address);
function tokenIdsToRegistered(uint tokenId) external view returns (bool);
function tokenIdsToLastWithdrawalDay(uint tokenId) external view returns (uint);
function tokenIdsToEndRewardsDay(uint tokenId) external view returns (uint);
function tokenIdsToDailyRewardAmount(uint tokenId) external view returns (uint);
function registerNftForRewards(uint tokenId) external;
function withdrawRewards(uint tokenId) external;
function currentDay() external view returns (uint256);
}
interface PulseBitcoinLockNFTInterface {
function ownerOf(uint256 tokenId) external returns (address);
}
contract PulseBitcoinLockNFTRewardsBulk is Ownable, ReentrancyGuard {
PulseBitcoinLockNFTRewardsInterface public plsbLockRewards;
address public txnFeeSendTo;
uint public baseTxnFee;
event TxnError(uint tokenId, string reason);
event TxnErrorBytes(uint tokenId, bytes reason);
event NotOwnerError(uint tokenId);
struct NftVariables {
uint tokenId;
bool isRegistered;
bool canWithdrawal;
uint withdrawalAmount;
}
constructor(address _txnFeeSendTo) {
txnFeeSendTo = _txnFeeSendTo;
baseTxnFee = 0.0007 ether;
}
receive() payable external {
payable(txnFeeSendTo).transfer(msg.value);
}
function _senderIsTokenOwner(uint tokenId) internal returns(bool) {
return msg.sender == PulseBitcoinLockNFTInterface(
plsbLockRewards.pulseBitcoinLockNftContractAddress()
).ownerOf(tokenId);
}
function _txnFee(uint tokenIdLength) internal view returns(uint) {
uint txnFee = baseTxnFee * tokenIdLength;
if(txnFee < baseTxnFee * 10) {
txnFee = baseTxnFee * 10;
}
return txnFee;
}
function fetchNftVariables(
uint[] calldata tokenIds
) public view returns(NftVariables[] memory) {
NftVariables[] memory variablesArray;
variablesArray = new NftVariables[](tokenIds.length);
for(uint i; i < tokenIds.length;) {
uint tokenId = tokenIds[i];
NftVariables memory nftVariables = NftVariables({
tokenId: tokenId,
isRegistered: false,
canWithdrawal: false,
withdrawalAmount: 0
});
if(plsbLockRewards.tokenIdsToRegistered(tokenId)) {
nftVariables.isRegistered = true;
if(
plsbLockRewards.tokenIdsToLastWithdrawalDay(tokenId) <
plsbLockRewards.tokenIdsToEndRewardsDay(tokenId)
&&
plsbLockRewards.currentDay() >
plsbLockRewards.tokenIdsToLastWithdrawalDay(tokenId)
) {
nftVariables.canWithdrawal = true;
uint256 totalDaysOfRewardsLeft =
plsbLockRewards.tokenIdsToEndRewardsDay(tokenId) -
plsbLockRewards.tokenIdsToLastWithdrawalDay(tokenId);
uint256 numOfDaysSinceLastWithdrawal =
plsbLockRewards.currentDay() -
plsbLockRewards.tokenIdsToLastWithdrawalDay(tokenId);
if (numOfDaysSinceLastWithdrawal > totalDaysOfRewardsLeft) {
numOfDaysSinceLastWithdrawal = totalDaysOfRewardsLeft;
}
nftVariables.withdrawalAmount =
plsbLockRewards.tokenIdsToDailyRewardAmount(tokenId) *
numOfDaysSinceLastWithdrawal;
}
}
variablesArray[i] = nftVariables;
unchecked {
i++;
}
}
return variablesArray;
}
function bulkRegister(uint[] calldata tokenIds) public payable nonReentrant {
uint tokenIdsLength = tokenIds.length;
uint txnFee = _txnFee(tokenIdsLength);
if(msg.value != txnFee) {
revert("Txn Fee invalid");
}
payable(txnFeeSendTo).transfer(txnFee);
for( uint i; i < tokenIdsLength; ) {
if(!_senderIsTokenOwner(tokenIds[i])) {
emit NotOwnerError(tokenIds[i]);
continue;
}
try plsbLockRewards.registerNftForRewards(tokenIds[i]) {
} catch Error(string memory reason) {
emit TxnError(tokenIds[i], reason);
} catch (bytes memory reason) {
emit TxnErrorBytes(tokenIds[i], reason);
}
unchecked {
i++;
}
}
}
function bulkWithdraw(uint[] calldata tokenIds) public payable nonReentrant {
uint tokenIdsLength = tokenIds.length;
uint txnFee = _txnFee(tokenIdsLength);
if(msg.value != txnFee) {
revert("Txn Fee invalid");
}
payable(txnFeeSendTo).transfer(txnFee);
for( uint i; i < tokenIdsLength; ) {
if(!_senderIsTokenOwner(tokenIds[i])) {
emit NotOwnerError(tokenIds[i]);
continue;
}
try plsbLockRewards.withdrawRewards(tokenIds[i]) {
} catch Error(string memory reason) {
emit TxnError(tokenIds[i], reason);
} catch (bytes memory reason) {
emit TxnErrorBytes(tokenIds[i], reason);
}
unchecked {
i++;
}
}
}
function configureLockRewards(address _plsbLockRewardsAddress) public onlyOwner {
plsbLockRewards = PulseBitcoinLockNFTRewardsInterface(_plsbLockRewardsAddress);
}
}
文件 4 的 4:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
}
{
"compilationTarget": {
"contracts/PulseBitcoinLockNFTRewardsBulk.sol": "PulseBitcoinLockNFTRewardsBulk"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_txnFeeSendTo","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NotOwnerError","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"TxnError","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TxnErrorBytes","type":"event"},{"inputs":[],"name":"baseTxnFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"bulkRegister","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"bulkWithdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_plsbLockRewardsAddress","type":"address"}],"name":"configureLockRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"fetchNftVariables","outputs":[{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"isRegistered","type":"bool"},{"internalType":"bool","name":"canWithdrawal","type":"bool"},{"internalType":"uint256","name":"withdrawalAmount","type":"uint256"}],"internalType":"struct PulseBitcoinLockNFTRewardsBulk.NftVariables[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"plsbLockRewards","outputs":[{"internalType":"contract PulseBitcoinLockNFTRewardsInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"txnFeeSendTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]