[英]Solidity calling contract with elevated permissions
I have two contracts, one for handling staking and one for minting a NFT.我有两份合约,一份用于处理抵押,一份用于铸造 NFT。 The flow I want is for the user to stake in frontend react app which will invoke the staking contract.我想要的流程是让用户在前端反应应用程序中进行质押,这将调用质押合同。 The user will then be eligible to mint a NFT when staked.然后,用户将有资格在抵押时铸造 NFT。
Now the issue I am facing is that because the minting role is called from stakingExample contract, which requires the user to invoke this, but as it has a critical function (mint) of the other contract, it should be protected with permissions such that only StakingExample can call NFTExample contract.现在我面临的问题是,因为铸币角色是从 stakingExample 合约中调用的,这需要用户调用它,但由于它具有另一个合约的关键功能(铸币),所以应该用权限保护它,这样只有StakingExample 可以调用 NFTExample 合约。
Is there a way to allow the user to run NFTExample with elevated permissions temporary in smart contract?有没有办法允许用户在智能合约中临时以提升的权限运行 NFTExample?
Example of staking contract:抵押合约示例:
// SPDX-License-Identifier: unlicensed
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract StakingExample is AccessControl {
bytes32 public constant CONTRACT_ROLE = keccak256("CONTRACT_ROLE");
NFTExample public _NFTExample;
...
function someStakingFunction() {
// code that stakes and
// set some variable that tracks if user have minted
}
function claimNFT(uint256 _pid, string memory _tokenURI) public onlyRole(CONTRACT_ROLE) {
// checks if user have unclaimed NFT
if (haveUnclaimed) {
_NFTExample.mintItem(msg.sender, _tokenURI)
}
}
}
Example of NFT contract: NFT合约示例:
// SPDX-License-Identifier: unlicensed
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract CMRGachaSeedNFT is ERC721URIStorage, AccessControl, ERC721Enumerable {
bytes32 public constant CONTRACT_ROLE = keccak256("CONTRACT_ROLE");
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
...
// Only Contract Role can call mint item, which mint item and transfers it to user's address
function mintItem(address _address, string memory _tokenURI)
public
onlyRole(CONTRACT_ROLE)
returns (uint256)
{
// Do some checks
// Mint
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(_address, newItemId);
_setTokenURI(newItemId, _tokenURI);
return newItemId;
}
}
You need to add one function in staking contract which shows amount of the staking:您需要在 staking 合约中添加一个函数来显示 staking 的数量:
function showStakeAmount() external view returns(uint256){
//I don't know your codes about this but you need a mapping to store
//the stake amount of each user and here you return it but something like this:
return StakingAmountOfUsers(msg.sender);
}
Then you need an interface of the staking contract and its address, also make an modifier in NFT contract (Following changes must be added):然后你需要一个质押合约的接口和地址,还要在 NFT 合约中做一个修饰符(必须添加以下更改):
interface StakingInterface{
function showStakeAmount() external view returns(uint256);
}
contract CMRGachaSeedNFT is ERC721URIStorage, AccessControl, ERC721Enumerable {
uint256 AmountThatShouldBeStaked;
StakingInterface StakingContract;
constructor(address STAKING_CONTRACT_ADDRESS){
StakingContract = StakingInterface(STAKING_CONTRACT_ADDRESS);
}
modifier isStaked(){
require(StakingContract.showStakeAmount() > AmountThatShouldBeStaked, "You did not stake enough amount of X token");
_;
}
function mintItem(address _address, string memory _tokenURI)
public
onlyRole(CONTRACT_ROLE)
returns (uint256)
isStaked()
{
//Continue coding...
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.