I’m trying to create an NFT purchase function but running into authorization issues. Here’s my current setup:
#[payable]
pub fn purchase_token(&mut self, nft_id: String) {
self.nft_contract.create_token(
nft_id,
buyer_account,
Some(metadata_info),
)
}
The problem is that the authorization check requires the predecessor to match the owner_id, but my owner_id is set to the contract’s account ID where it’s deployed.
assert_eq!(env::predecessor_account_id(), self.owner_id, "Access denied");
When I try to call this through a user account like alice, I get an unauthorized error:
call!(
alice,
my_contract.purchase_token("456".to_owned()),
deposit = to_yocto("5")
).assert_success();
The error shows that alice’s account doesn’t match the contract name, so access is denied. How can I properly structure this so the contract can mint tokens on behalf of users who call the purchase function?
hmm interesting problem! so if i’m understanding this correctly, you’ve got your contract set up as the owner but then you’re checking if the caller (alice) matches that owner id in the purchase function? that’s definitely gonna block everyone except the contract itself lol
but im curious about your overall architecture here - are you trying to build this as a single contract that handles both the marketplace logic AND the nft minting? or do you have seperate contracts for each? because the way you’re calling self.nft_contract.create_token() makes it look like you’re doing cross-contract calls
if thats the case, then yeah like the others mentioned you’d want to remove that owner check from purchase entirely. but what im wondering is - how are you handling the payment flow? like when alice sends 5 NEAR with her purchase call, are you planning to keep some as marketplace fees and forward the rest to the nft contract?
also just curious about your metadata setup - are you generating that dynamically based on the nft_id or do you have it prestored somewhere? seems like there might be some interesting design decisions to unpack here that could affect how you structure the auth!
The issue stems from your authorization logic blocking legitimate user purchases. You need to restructure the access control to differentiate between administrative functions and user-facing operations. Remove the owner assertion from the purchase function entirely since users should be able to buy NFTs. Instead, implement role-based permissions where only administrative functions like changing contract settings require owner privileges. For the NFT minting, you’ll need to use cross-contract calls with proper promise handling. The contract itself should be registered as an authorized minter on the NFT contract, not individual users. Your purchase function should validate payment amounts and handle the minting promise appropriately. I encountered similar authorization headaches when building marketplace contracts. The key insight is that your main contract acts as an intermediary - users interact with your contract, which then handles the NFT operations using its own authority. Make sure your contract account has the necessary permissions on the NFT contract side.
you’re mixing up authorization levels here. the purchase function shouldnt have that owner check at all - thats blocking regular users from buying. save owner assertions for admin stuff only. your contract needs to be whitelisted on the nft contract side to mint tokens, not the end users.