Open aramalipoor opened 3 years ago
For a PoC so far this is what I ended up with, but currently have 2 problems:
Should this operation automatically list the sale order on OpenSea? If so I don't see it on testnets.opensea at least.
bytes constant emptyBytes = bytes("");
bytes constant replacementPattern = bytes(hex"000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000");
function putForSale(
address owner,
uint256 tokenId,
uint256 salePrice
) public virtual isDirectory()
{
uint zero = 0;
uint one = 1;
address zeroAddr = address(0);
bytes memory transferCalldata = abi.encodeWithSignature("transferFrom(address,address,uint256)", owner, zeroAddr, tokenId);
address[7] memory addrs;
uint[9] memory uints;
{
addrs = [
// Exchange
address(_wyvernExchange),
// Maker
address(this),
// Taker
zeroAddr,
// Fee Recipient
_openSeaWallet,
// Target (Asset Contract)
address(_directory),
// Static Target
zeroAddr,
// Token used to pay for the order, or the zero-address as a sentinel value for Ether
zeroAddr
];
}
{
uints = [
// Maker Relayer Fee
500,
// Taker Relayer Fee
zero,
// Maker Protocol Fee
zero,
// Taker Protocol Fee
zero,
// Base price of the order (in paymentTokens)
salePrice,
// Auction extra parameter - minimum bid increment for English auctions, starting/ending price difference
zero,
// Expiration timestamp - 0 for no expiry
block.timestamp,
zero,
// Order salt, used to prevent duplicate hashes
uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp)))
];
}
{
_approveWyvernOrder(
addrs,
uints,
transferCalldata
);
}
}
function _approveWyvernOrder(
address[7] memory addrs,
uint[9] memory uints,
bytes memory transferCalldata
) internal {
_wyvernExchange.approveOrder_(
addrs,
uints,
// Fee Method (split fee): Maker fees are deducted from the token amount that the maker receives. Taker fees are extra tokens that must be paid by the taker.
WyvernExchangeInterface.FeeMethod.SplitFee,
// Side (sell)
WyvernExchangeInterface.Side.Sell,
// Sale Kind (fixed price)
WyvernExchangeInterface.SaleKind.FixedPrice,
// How to call (call)
WyvernExchangeInterface.HowToCall.Call,
// Call Data
transferCalldata,
// Replacement Pattern
replacementPattern,
// staticExtradata
emptyBytes,
// orderbookInclusionDesired
true
);
}
This is an example NFT where I called approveOrder_ but don't see it listed on OpenSea: https://testnets.opensea.io/assets/0xda25087323285AE25e00E8C373a9184fb558D831/100 on this transaction https://rinkeby.etherscan.io/tx/0xe32bf43e6a08e9fa0e28c54e55db68d0d2849d0c93e3d26acb81ab880cabfc47#eventlog
Now I figured out I have to call OpenSea API to "post" the order...
There's a problem which I'm guessing is on OpenSea backend side. I'm using a different "maker" than the "owner" in the calldata...
So currently, I have marker
= Our Marketer Contract, and owner
= owner of tokenId, and I'm getting this error from OpenSea backend:
{
"success": false,
"errors": [
"[\"Transfer calldata doesn't match.\"]"
]
}
And I think this is because OpenSea backend expects "owner == marketer" which is just one way of working with Wyvern protocol if I'm not mistaken...
For more context, calldata is for transferFrom(owner, null_address, tokenId)
, but the maker is our Marketer smart contract, so they are different. If I set maker = "owner" the contract fails due to maker != sender
, but if set owner = "marker" then the contract fails because the Marketer (maker) is not the actual owner of tokenId...
curl --location --request POST 'https://rinkeby-api.opensea.io/wyvern/v1/orders/post/' --header 'Content-Type: application/json' --data-raw '{
"exchange": "0x5206e78b21ce315ce284fb24cf05e0585a93b1d9",
"maker": "0x3f539db004cb22c96d69d0e3eb8974d46ed93254",
"taker": "0x0000000000000000000000000000000000000000",
"makerRelayerFee": "250",
"takerRelayerFee": "0",
"makerProtocolFee": "0",
"takerProtocolFee": "0",
"makerReferrerFee": "0",
"feeMethod": 1,
"feeRecipient": "0x5b3256965e7c3cf26e11fcaf296dfc8807c01073",
"side": 1,
"saleKind": 0,
"target": "0xda25087323285ae25e00e8c373a9184fb558d831",
"howToCall": 0,
"calldata": "0x23b872dd000000000000000000000000431922e8ede1ce07ed80c89ac4c302e23dc6ba2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064",
"replacementPattern": "0x000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000",
"staticTarget": "0x0000000000000000000000000000000000000000",
"staticExtradata": "0x",
"paymentToken": "0x0000000000000000000000000000000000000000",
"quantity": "1",
"basePrice": "550000000000000000",
"extra": "0",
"listingTime": "1624714038",
"expirationTime": "0",
"salt": "108978690099335258361352357558901730935341035577208231443103633475927170030228",
"metadata": {
"asset": {
"id": "100",
"address": "0xda25087323285ae25e00e8c373a9184fb558d831"
},
"schema": "ERC721"
},
"hash": "0xb48cd508ec5caab9ab9b4fcb4d83afeeb53b009dea3393ca9a167158bb38d1fe"
}'
@cwgoes @MarvinJanssen would you be able to help me on above?
@aramalipoor Hey Aram, we are also trying to initiate a sell and buy orders via smart contract. Have you manage to make any progress?
Hi @Rotemy @aramalipoor -- we are facing a similar issue Were you able to find a solution?
Yes, but the seller or buyer should either be the smart contract or the user has to sign the sell/buy order in advanced
Hi @Rotemy,
Thanks a lot for your reply.
Then, this would be correct?
bytes memory transferCalldata = abi.encodeWithSignature("transferFrom(address,address,uint256)", address(this), zeroAddr, tokenId);
where address(this) would be the contract address and then the buyer.
well, there is a replacement pattern that will change the address(0) to the buyer, so you can keep it like that or change zeroAddres to buyer address.
On Fri, Nov 19, 2021 at 2:24 PM priviprotocol @.***> wrote:
Hi Rotemy,
Thanks a lot for your reply.
Then, this would be correct? bytes memory transferCalldata = abi.encodeWithSignature("transferFrom(address,address,uint256)", address(this), zeroAddr, tokenId);`
where address(this) would be the contract address and then the buyer.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/wyvernprotocol/wyvern-v3/issues/55#issuecomment-974027514, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAFOG75E5AWCAUIIK6WPQRLUMY6YVANCNFSM47HLK4KQ .
-- Kind regards,
Rotem Yakir +972547545695
Thanks again for the answer @Rotemy. Let me state better our problem. We are trying to list a selling offer on Opensea from our contract.
This is the post request we are doing:
{
"exchange": "0x5206e78b21ce315ce284fb24cf05e0585a93b1d9",
"maker": "0x568A0f32BC48f278fe3C822E9992dD478598b3B1",
"taker": "0x0000000000000000000000000000000000000000",
"makerRelayerFee": "250",
"takerRelayerFee": "0",
"makerProtocolFee": "0",
"takerProtocolFee": "0",
"makerReferrerFee": "0",
"feeMethod": 0,
"feeRecipient": "0x5b3256965e7c3cf26e11fcaf296dfc8807c01073",
"side": 1,
"saleKind": 0,
"target": "0x8385c95eb77ceab24f8bb05b33dc7602840c0ba1",
"howToCall": 0,
"calldata": "23B872DD000000000000000000000000568A0F32BC48F278FE3C822E9992DD478598B3B100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003",
"replacementPattern": "000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000000000000000000000000000000000000000000000000000000000000000",
"staticTarget": "0x0000000000000000000000000000000000000000",
"staticExtradata": "0x",
"paymentToken": "0x0000000000000000000000000000000000000000",
"quantity": "1",
"basePrice": "100000000000000000000",
"extra": "0",
"listingTime": "1637328412",
"expirationTime": "0",
"salt": "70178943407415076223843289749154878162928002278408319126229368582024804639243",
"metadata": {
"asset": {
"id": "3",
"address": "0x8385c95eb77ceab24f8bb05b33dc7602840c0ba1"
},
"schema": "ERC721"
},
"hash": "0xced35f245951d3622eeee38066d3a71ab1218e7fcc7d451d213d133d5d0dcef1"
}
after calling approveOrder on Wyvern Exchange https://rinkeby.etherscan.io/tx/0x2153ca6f7cc1aac8f08e7a65df424bab1b2d4b3209dccd9d9a6f0c4885cb6602#eventlog
However the response we are getting is:
"errors": [ "['You must approve assets #3 for trading before creating an order']"
I would be great if you could give some guidance or support on that. Thanks in advance.
Hi @Rotemy, @priviprotocol, I am also trying to initiate sell order via smart contract. I tested approveOrder_() based on aramalipoor's code above, but it did not work. Did you achieve that in a completely different way than aramalipoor? Could you give me some advice?
Hello guys, do you know how to get the orderbook of a token from the wyvern exchange?
Hello guys, do you know how to get the orderbook of a token from the wyvern exchange?
you mean how to get order data for available atomic matches on Wyvern? I want to know the same
Hello there,
Thanks for the amazing platform! We're building a NFT platform with some special rules, because of these (specifically that "transferFrom" and "approve" cannot be called by owners themselves) we have to automatically list them on OpenSea.
From my understanding so far we need to call
approveOrder_
from a contract who has the ability to do approve and transferFrom on those NFTs. We were thinking of having a "Marketer" contract which has a special access to do these operations on all NFTs on behalf of holders.Assuming, above is correct there are a few questions I have:
Thank you so much in advance :)