1

I am trying to perform a certain action say like selling a token only when the message sent to a contract is signed by the contract owner. I knew how I would do this in js, but I am having a hard time finding a clear documentation for python. Here is what I have at the moment.

my solidity

function buy_token(string memory tokenURI, bytes memory signature) payable public{

    // Make sure this token uri is signed by the owner of the contract
    // to the recipient that is asking to buy 
    
    address signer_address = recoverSigner(keccak256(abi.encodePacked(tokenURI, msg.sender)), signature); 
    require(signer_address == minter, "NFT not authorized by this contract");
    
    require(msg.value >= cprice, "Insufficient funds to buy");

    require(minter != msg.sender, "Cant sell to owner");

    uint256 mint_id = mint(tokenURI);
    
      // transfer the token to the buyer
    _transfer(minter, msg.sender, mint_id);
}

// functions from documentatations
function recoverSigner(bytes32 message, bytes memory sig)
   public
   pure
   returns (address)
{
   uint8 v;
   bytes32 r;
   bytes32 s;
   (v, r, s) = splitSignature(sig);
   return ecrecover(message, v, r, s);
}
function splitSignature(bytes memory sig)
    public
    pure
    returns (uint8, bytes32, bytes32)
{
    require(sig.length == 65, 'Wrong byte lenght');
    
    bytes32 r;
    bytes32 s;
    uint8 v;
    assembly {
        // first 32 bytes, after the length prefix
        r := mload(add(sig, 32))
        // second 32 bytes
        s := mload(add(sig, 64))
        // final byte (first byte of the next 32 bytes)
        v := byte(0, mload(add(sig, 96)))
    }
    return (v, r, s);
}

and here is my python brownie code, which tries to emulate both a deployer and a user. The deployer signs a message and gives it to the user and the user tries to buy a token using the signed message.

from brownie import Contract, accounts
from web3.auto import w3
from eth_account.messages import encode_defunct
from eth_abi.packed import encode_abi_packed
from eth_utils import keccak
def main():
    # This part is for test in the real program the smart
    # contract would alredy be deployed
    deployer = accounts.add()
    Contract.deploy({
        'from':deployer
    })

    msg = """JSON FORMATED STRING"""
        
    hash = keccak(encode_abi_packed(['string','address'],[tokenURI, accounts[0].address]))
    message = encode_defunct(text=hash.hex())
   
    signed_message =  w3.eth.account.sign_message(message, private_key=deployer.private_key)

    signed = str(signed_message.messageHash.hex())

    tx = Contract[0].buy_token(tokenURI, signed,{'from':accounts[0], 'value': Contract[0].cprice() + 10000000000})

   print(tx.info, tx.events)

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.