Reputation: 711
I'm trying to develop a set of contracts in where an ERC721 token is auctioned off, then the winner gets the token placed into their wallet. I'm not entirely sure how to structure this. These are the contracts I was thinking would be needed.
WALLET
AuctionFactory
contract and saves the addressAUCTIONFACTORY
Auction
contract upon command, with the item being the ERC721 token specifiedAUCTION
Wallet
, allowing manipulation of the mapping
state variable found in the contract, placing ERC721 tokens won into the winners walletThe problem is that Auction
can't inherit from Wallet
. The compiler will throw an error when AuctionFactory
tries to deploy an auction - cannot create instance of derived or same contract
. And that makes sense to me, since Wallet
deploys the factory, and if the factory deploys an Auction
that inherits from Wallet
, it's technically deploying its parent contract.
So my question is, how can I structure this set of contracts? How can I allow an instance of an auction contract to communicate and manipulate with a store on another contract?
Upvotes: 3
Views: 1198
Reputation: 39243
Here is an example contract which can deposit tokens and then auction them off. This is a basic auction model which shows the control flow for transferring possession of the token.
Here is the setup. First we have to import the ERC-721 headers. I am using the reference implementation for ERC-721 for this:
pragma solidity 0.5.1;
import "https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/erc721.sol";
import "https://github.com/0xcert/ethereum-erc721/src/contracts/tokens/erc721-token-receiver.sol";
Here is the contract and the main data structure:
// This implements an ERC-721 auction by taking ownership of tokens
contract CollectableAuction is ERC721TokenReceiver {
mapping (uint256 => AuctionDetails) auctionDetails;
struct AuctionDetails {
ERC721 nftContract;
bool bidIsComplete;
address seller;
address winningBidder;
uint256 tokenId;
}
}
We add in the deposit mechanism. This works by allowing people to send tokens directly to the auction contract. You may implement a different mechanism to start auctions, but this one works just as well.
// Deposit an asset and start an auction
function onERC721Received(
address,
address from,
uint256 tokenId,
bytes calldata
)
external
returns(bytes4)
{
uint256 auctionId = uint256(keccak256(abi.encode(uint256(msg.sender), tokenId)));
auctionDetails[auctionId] = AuctionDetails({
nftContract: ERC721(msg.sender),
bidIsComplete: false,
seller: from,
winningBidder: address(0),
tokenId: tokenId
});
return 0x150b7a02;
}
Here is a mock implementation for your auction process. Your actual auction will certainly be more complicated.
function completeAuction(uint256 auctionId) external {
auctionDetails[auctionId].bidIsComplete = true;
}
Lastly, when the auction is done then the winning bidder needs to take the token.
function withdraw(uint256 auctionId) external {
AuctionDetails storage details = auctionDetails[auctionId];
require(details.bidIsComplete);
require(msg.sender == details.winningBidder);
// Collect money from winning bidder
details.nftContract.safeTransferFrom(address(this), details.winningBidder, details.tokenId);
// Send money to seller
// Do event logging
delete auctionDetails[auctionId];
}
The above is a fully-functioning starting point for this project.
Upvotes: 2
Reputation: 2078
I'm not sure why you need to inherit from a Wallet
contract. The Auction structure should be something like:
createAuction
from your contract to create an auctioncreateAuction(tokenId, minPrice, duration)
will:
transferFrom
function from your ERC721 contract to transfer the ownership from current owner to the Auction contract itself, something like: erc721.transferFrom(owner, this, tokenId)
. This is required later when you have to transfer the ownership to the buyer.bidOnAuction(tokenId)
. Check the parameters (msg.value > minPrice
, duration, etc.). And if these are bid winning conditions, then you transfer the money to the seller (owner) and you transfer the token owrnership from your contract to the buyer, again by calling the erc721 method: erc721.transferFrom(this, msg.sender, tokenId)
.The Auction contract works as an escrow, it keeps the ERC721 token ownership until the auction is finished (bought or cancelled). You don't have to "manipulate ownership", you only have to let the owner transfer the token to your contract and then, your contract transfer the ownership back to the previous owner if the auction was cancelled or to the buyer if the auction was completed.
Upvotes: 0