I'm getting a revert when trying to transfer a token from another contract, I'm calling the function from an Auctions contract, for example, when the max bidder claims the reward they get the token but I'm getting a revert because of the msg.sender
since it changes to the address of the Auctions contract.
This is the current function of the Auctions contract:
function withdraw(uint256 _auctionId) public {
AuctionData storage auction = auctions[_auctionId];
require(!auction.isOpen);
uint256 payout;
if(msg.sender == auction.owner) {
payout = auction.maxBid;
auction.maxBid = 0;
}
// We ensure the msg.sender isn't the max bidder nor the owner.
// If the address is the owner that would evaluate to true two times (above and this one)
// and 'payout' wouldn't be correct.
// If msg.sender didn't bid then the payout will be 0 anyhow.
if(msg.sender != auction.maxBidder && msg.sender != auction.owner) {
payout = auction.bids[msg.sender];
auction.bids[msg.sender] = 0;
}
if(msg.sender == auction.maxBidder) {
// Manually sends the token from owner to maxBidder.
// CToken(ctoken).transferTokenTo(auction.owner, msg.sender, auction.horse);
delete auction.maxBidder;
}
msg.sender.transfer(payout);
emit Withdraw(msg.sender, payout);
}
The relevant part is the if(msg.sender == auction.maxBidder) {}
The Token contract only calls approve
/ safeTransferFrom
from OpenZeppelin's contract.
So, what are my options here to avoid this revert / maintain the msg.sender
to the address that sent the transaction and not the contract?
Edit: Token contract
pragma solidity ^0.4.2;
import "./ERC721Token.sol";
import "./CryptofieldBase.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
contract CToken is ERC721Token {
using SafeMath for uint256;
uint256 stallionsAvailable = 168;
uint256 maresAvailable = 379;
uint256 coltsAvailable = 230;
uint256 filliesAvailable = 334;
// Variable for enumeration.
address[] addresses;
address cryptofieldBase;
constructor(address _cryptofieldBase) ERC721Token("CToken", "CT") public {
cryptofieldBase = _cryptofieldBase;
}
/* @dev Returns an array of ids of horses owned by '_from' */
function getOwnedTokens(address _from) public view returns(uint256[]) {
return super.getOwnedTokens(_from);
}
function createHorse(address _owner, string _hash) public payable {
require(stallionsAvailable > 0);
uint256 tokenId = addresses.push(_owner) - 1;
_mint(_owner, tokenId);
CryptofieldBase(cryptofieldBase).buyHorse(_owner, _hash);
stallionsAvailable = stallionsAvailable.sub(1);
}
function transferTokenTo(address _from, address _to, uint256 _tokenId) public {
safeTransferFrom(_from, _to, _tokenId);
}
function ownerOfToken(uint256 _tokenId) public view returns(address) {
return ownerOf(_tokenId);
}
function approveAddress(address _to, uint256 _tokenId) public {
approve(_to, _tokenId);
}
/*
@dev Transfer a token of '_from' to '_to'
*/
function tokenSold(address _from, address _to, uint256 _tokenId) public {
safeTransferFrom(_from, _to, _tokenId);
CryptofieldBase(cryptofieldBase).horseSold(_tokenId);
}
}
safeTransferFrom
to pass abytes
parameter that will be passed to the receiving contract functiononERC721Received
. That should allow the user to create a single transaction withsafeTransferFrom
and if your auction as recipient and has a methodonERC721Received
to complete the process.