Skip to content

Commit

Permalink
chore: adding basic NFTMultiplier implementation, deploy script and c…
Browse files Browse the repository at this point in the history
…onfig with tests

 Changes to be committed:
  • Loading branch information
RonTuretzky committed Sep 28, 2024
1 parent fffe13b commit fc1221b
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 0 deletions.
64 changes: 64 additions & 0 deletions script/deploy/DeployNFTMultiplier.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import {Script} from "forge-std/Script.sol";
import {NFTMultiplier} from "src/multipliers/NFTMultiplier.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {console} from "forge-std/console.sol";

contract DeployNFTMultiplier is Script {
function run() external {
uint256 deployerPrivateKey;
address nftContractAddress;
uint256 initialMultiplyingFactor;
uint256 validUntilBlock;

string memory configPath = "deploy_config.json";
string memory jsonData;
// Try to read the JSON file, if it doesn't exist or can't be read, catch the error
try vm.readFile(configPath) returns (string memory data) {
jsonData = data;
} catch {
console.log("Config file not found or couldn't be read. Falling back to environment variables.");
jsonData = "";
}

if (bytes(jsonData).length > 0) {
// Read from JSON if file exists
deployerPrivateKey = vm.parseJsonUint(jsonData, ".deployerPrivateKey");
nftContractAddress = vm.parseJsonAddress(jsonData, ".nftContractAddress");
initialMultiplyingFactor = vm.parseJsonUint(jsonData, ".initialMultiplyingFactor");
validUntilBlock = vm.parseJsonUint(jsonData, ".validUntilBlock");
} else {
// Fall back to environment variables
deployerPrivateKey = vm.envUint("PRIVATE_KEY");
nftContractAddress = vm.envAddress("NFT_CONTRACT_ADDRESS");
initialMultiplyingFactor = vm.envUint("INITIAL_MULTIPLYING_FACTOR");
validUntilBlock = vm.envUint("VALID_UNTIL_BLOCK");
}

// Check if all required variables are set
require(deployerPrivateKey != 0, "Deployer private key not set");
require(nftContractAddress != address(0), "NFT contract address not set");
require(initialMultiplyingFactor != 0, "Initial multiplying factor not set");
require(validUntilBlock != 0, "Valid until block not set");

vm.startBroadcast(deployerPrivateKey);

NFTMultiplier implementation = new NFTMultiplier();

bytes memory initData = abi.encodeWithSelector(
NFTMultiplier.initialize.selector, IERC721(nftContractAddress), initialMultiplyingFactor, validUntilBlock
);

TransparentUpgradeableProxy proxy =
new TransparentUpgradeableProxy(address(implementation), vm.addr(deployerPrivateKey), initData);

NFTMultiplier nftMultiplier = NFTMultiplier(address(proxy));

vm.stopBroadcast();

console.log("NFTMultiplier deployed at:", address(nftMultiplier));
}
}
6 changes: 6 additions & 0 deletions script/deploy/config/deployNFTMul.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"deployerPrivateKey": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
"nftContractAddress": "0x1234567890123456789012345678901234567890",
"initialMultiplyingFactor": 100,
"validUntilBlock": 1000000
}
80 changes: 80 additions & 0 deletions src/multipliers/NFTMultiplier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {INFTMultiplier} from "src/interfaces/multipliers/INFTMultiplier.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/// @title NFT Multiplier
/// @notice Implementation of INFTMultiplier interface
/// @dev Provides multiplying factors based on NFT ownership
contract NFTMultiplier is INFTMultiplier, Initializable, OwnableUpgradeable {
IERC721 public nftContract;
uint256 public multiplyingFactor;
uint256 public validUntilBlock;

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

/// @notice Initializer function to set the NFT contract address and initial multiplying factor
/// @param _nftContract Address of the NFT contract
/// @param _initialMultiplyingFactor Initial multiplying factor (in basis points, e.g., 15000 for 1.5x)
/// @param _validUntilBlock Block number until which the multiplier is valid
function initialize(IERC721 _nftContract, uint256 _initialMultiplyingFactor, uint256 _validUntilBlock)
public
initializer
{
__Ownable_init(msg.sender);

nftContract = _nftContract;
multiplyingFactor = _initialMultiplyingFactor;
validUntilBlock = _validUntilBlock;
}

/// @notice Get the address of the NFT contract
/// @return The address of the NFT contract used for checking ownership
function NFTAddress() external view override returns (IERC721) {
return nftContract;
}

/// @notice Check if a user owns an NFT
/// @param user The address of the user to check
/// @return True if the user owns at least one NFT, false otherwise
function hasNFT(address user) public view override returns (bool) {
return nftContract.balanceOf(user) > 0;
}

/// @notice Get the multiplying factor for a given user
/// @param user The address of the user
/// @return The multiplying factor if the user owns an NFT, 0 otherwise
function getMultiplyingFactor(address user) external view override returns (uint256) {
return hasNFT(user) ? multiplyingFactor : 0;
}

/// @notice Get the block number until which the multiplier is valid
/// @return The block number until which the multiplier is valid
function validUntil(address /* user */ ) external view override returns (uint256) {
return validUntilBlock;
}

/// @notice Update the multiplying factor
/// @param _newMultiplyingFactor New multiplying factor (in basis points)
function updateMultiplyingFactor(uint256 _newMultiplyingFactor) external onlyOwner {
multiplyingFactor = _newMultiplyingFactor;
}

/// @notice Update the valid until block
/// @param _newValidUntilBlock New block number until which the multiplier is valid
function updateValidUntilBlock(uint256 _newValidUntilBlock) external onlyOwner {
validUntilBlock = _newValidUntilBlock;
}

/// @notice Update the NFT contract address
/// @param _newNFTContract New NFT contract address
function updateNFTContract(IERC721 _newNFTContract) external onlyOwner {
nftContract = _newNFTContract;
}
}

0 comments on commit fc1221b

Please sign in to comment.