1

I'm trying to test a smart contract function on the rinkeby test network, which migrates multiple tokens to the new contract. I.e. I want to burn ERC-721 tokens (send them to a burn address), which are stored on the Opensea contract, and then remint it on the new contract.

Everything worked fine when I tested the function on a local etherum network fork (with ganache-cli) but on the rinkeby network I get the following error:

errors.js:87 Uncaught (in promise) Error: Transaction has been reverted by the EVM:
{
  "blockHash": "0x1b6f3907c56626ed6e66a090fdc5c4e14723fa4be11137227c5fcb20f89a7c8c",
  "blockNumber": 9780743,
  "contractAddress": null,
  "cumulativeGasUsed": 823380,
  "effectiveGasPrice": "0x9502f90a",
  "from": "0x4e3a2cd1904ba26f9bbcd196802dceec94cf97fd",
  "gasUsed": 204890,
  "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "status": false,
  "to": "0x33a7bbd2f44c012ee19c0e0a9190bb6ba555ffb4",
  "transactionHash": "0x8e2cbd9bc333fd56788b51e21568be02a62548468f43ac86859766655818dce1",
  "transactionIndex": 6,
  "type": "0x2",
  "events": {}
}
    at Object.TransactionError (errors.js:87)
    at Object.TransactionRevertedWithoutReasonError (errors.js:98)
    at index.js:395

On Etherscan.io I get this additional error message under 'Status':

Fail with error 'AssetContractShared#_requireMintable: ONLY_CREATOR_ALLOWED'

Here is the smart contract function I'm calling. It works fine when I remove the for loop with the Opensea(openseaSharedAddress).safeTransferFrom(msg.sender, burnAddress, oldIds[j], 1, ""); function

function batchMigration(uint256[] memory oldIds, uint256[] memory newIds, bytes32[] memory leaves, bytes32[][] memory proofs) external {
        for (uint i = 0; i < oldIds.length; i++) {
            // Don't allow reminting
            require(!_exists(newIds[i]), "Token already minted");

            // Verify that (oldId, newId) correspond to the Merkle leaf
            require(keccak256(abi.encodePacked(oldIds[i], newIds[i])) == leaves[i], "Ids don't match Merkle leaf");

            // Verify that (oldId, newId) is a valid pair in the Merkle tree
            //require(verify(merkleRoot, leaves[i], proofs[i]), "Not a valid element in the Merkle tree");

            // Verify that msg.sender is the owner of the old token
            require(Opensea(openseaSharedAddress).balanceOf(msg.sender, oldIds[i]), "Only token owner can mintAndBurn");
        }

        for (uint j = 0; j < oldIds.length; j++) {
            Opensea(openseaSharedAddress).safeTransferFrom(msg.sender, burnAddress, oldIds[j], 1, "");
        }
    }

And here web3 part where I call the batch migration function:

await smartContract.methods
           .batchMigration(oldIds, newIds, leaves, proofs)
           .send({
               from: walletAddress, //accounts[0]
               gasLimit: 6721975,
           }).on('transactionHash', function (hash) {
                console.log(hash)
           });

Before I'm calling the batch migration function I'm setting ApprovalForAll, so this shouldn't be the problem:

await openseaContract.methods.setApprovalForAll(SMART_CONTRACT_ADDRESS, true).send({
            from: walletAddress,
        });

Has anyone an idea why this error occurs? Thanks

Heyho
  • 11
  • 1

1 Answers1

0

I was having the same problem and after testing a bit, I could find a solution.

As I've just posted here https://ethereum.stackexchange.com/questions/111077/error-execution-reverted-assetcontractsharedcreatoronly-only-creator-allowed, the contract is calling the minting function before transferring the token. Calling the minting function leads to the call to a modifier, that itself checks the tokenOwner.

The solution is to check if the token has been minted and mint it, before it can be transferred by the other address (that has been approved).

  • test the balance of the token
  • if it has no balance, mint it first (from the transferring account)
  • then you can setApprovalForAll
  • then the transfer should work