klaytn / caver-js

Official caver-js repository
GNU Lesser General Public License v3.0
114 stars 75 forks source link

Need help: `contract.methods.transferFrom()` keeps returning errors #373

Closed zjj010104 closed 4 years ago

zjj010104 commented 4 years ago

Code:

  const caver = new Caver('https://api.cypress.klaytn.net:8651')

  // WKLAY address
  const contractAddress = '0x70F23a76f1dcf931B2B5352a60CF0AFE42476982'
  const account = '0xbb9616D46321fef28AA2564FbfC3Bc4fA60CE8B8'
  const account2 = '0xC0174d687765A82e13d69b1f44fABCA20E5D82Ce'
  const myContract = new caver.klay.Contract(abi, contractAddress, {
    from: account,
    gasPrice: '25000000000'
  });

  myContract.methods
    .approve(account, 1)
    .call({}, function(error, result) {
      console.log('------- approve: ', error, result);
      if (result === false) {
        return;
      }
      myContract.methods
        .transferFrom(account, account2, 1).call({}, function(error, result) {
          console.log('------- results: ', error, result);
        });
    });

Error:

------- approve:  null true
------- results:  Error: Returned error: evm: execution reverted

Did I do anything wrong here? Thank you in advance!

jimni1222 commented 4 years ago

Hi :) Thank you for posting an issue.

Can I receive the abi and byte code of the deployed contract?

When looking at the code alone, the method using caver-js doesn't seem to be a problem. "evm reverted" is an error transmitted from Klaytn Platform.

Additional information is needed to determine the reason in more detail.

zjj010104 commented 4 years ago

Thank you for the fast response! I actually somehow get the approve work fine. But transferFrom is not getting the error. I updated the issue content.

Is the following info the right context?

code:

pragma solidity ^0.4.24;

contract WKLAY {
    string public name     = "Wrapped Klay";
    string public symbol   = "WKLAY";
    uint8  public decimals = 18;

    event  Approval(address indexed src, address indexed guy, uint wad);
    event  Transfer(address indexed src, address indexed dst, uint wad);
    event  Deposit(address indexed dst, uint wad);
    event  Withdrawal(address indexed src, uint wad);

    mapping (address => uint)                       public  balanceOf;
    mapping (address => mapping (address => uint))  public  allowance;

    function() public payable {
        deposit();
    }
    function deposit() public payable {
        balanceOf[msg.sender] += msg.value;
        emit Deposit(msg.sender, msg.value);
    }
    function withdraw(uint wad) public {
        require(balanceOf[msg.sender] >= wad);
        balanceOf[msg.sender] -= wad;
        msg.sender.transfer(wad);
        emit Withdrawal(msg.sender, wad);
    }

    function totalSupply() public view returns (uint) {
        return address(this).balance;
    }

    function approve(address guy, uint wad) public returns (bool) {
        allowance[msg.sender][guy] = wad;
        emit Approval(msg.sender, guy, wad);
        return true;
    }

    function transfer(address dst, uint wad) public returns (bool) {
        return transferFrom(msg.sender, dst, wad);
    }

    function transferFrom(address src, address dst, uint wad)
        public
        returns (bool)
    {
        require(balanceOf[src] >= wad);

        if (src != msg.sender && allowance[src][msg.sender] != uint(-1)) {
            require(allowance[src][msg.sender] >= wad);
            allowance[src][msg.sender] -= wad;
        }

        balanceOf[src] -= wad;
        balanceOf[dst] += wad;

        emit Transfer(src, dst, wad);

        return true;
    }
}

abi:

{
  "contractName": "WKLAY",
  "abi": [
    {
      "constant": true,
      "inputs": [],
      "name": "name",
      "outputs": [
        {
          "name": "",
          "type": "string"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "decimals",
      "outputs": [
        {
          "name": "",
          "type": "uint8"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "name": "",
          "type": "address"
        }
      ],
      "name": "balanceOf",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "symbol",
      "outputs": [
        {
          "name": "",
          "type": "string"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [
        {
          "name": "",
          "type": "address"
        },
        {
          "name": "",
          "type": "address"
        }
      ],
      "name": "allowance",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "payable": true,
      "stateMutability": "payable",
      "type": "fallback"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "src",
          "type": "address"
        },
        {
          "indexed": true,
          "name": "guy",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "Approval",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "src",
          "type": "address"
        },
        {
          "indexed": true,
          "name": "dst",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "Transfer",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "dst",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "Deposit",
      "type": "event"
    },
    {
      "anonymous": false,
      "inputs": [
        {
          "indexed": true,
          "name": "src",
          "type": "address"
        },
        {
          "indexed": false,
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "Withdrawal",
      "type": "event"
    },
    {
      "constant": false,
      "inputs": [],
      "name": "deposit",
      "outputs": [],
      "payable": true,
      "stateMutability": "payable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "withdraw",
      "outputs": [],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": true,
      "inputs": [],
      "name": "totalSupply",
      "outputs": [
        {
          "name": "",
          "type": "uint256"
        }
      ],
      "payable": false,
      "stateMutability": "view",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "guy",
          "type": "address"
        },
        {
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "approve",
      "outputs": [
        {
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "dst",
          "type": "address"
        },
        {
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "transfer",
      "outputs": [
        {
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    },
    {
      "constant": false,
      "inputs": [
        {
          "name": "src",
          "type": "address"
        },
        {
          "name": "dst",
          "type": "address"
        },
        {
          "name": "wad",
          "type": "uint256"
        }
      ],
      "name": "transferFrom",
      "outputs": [
        {
          "name": "",
          "type": "bool"
        }
      ],
      "payable": false,
      "stateMutability": "nonpayable",
      "type": "function"
    }
  ]}
jimni1222 commented 4 years ago

Is there any reason to use call?

In the case of a function that actually writes, deletes, or updates data in a smart contract, [send](https://docs.klaytn.com/bapp/sdk/caver-js/v1.4.1/api-references/caver.klay.contract#methods -mymethod-send) must be used.

In the code above, change .call() to .send() and define the gas required for transaction as.send({gas: '0x...'}) like this. (You can define from also inside of the object)

zjj010104 commented 4 years ago

Thank you very much for your patience! I'm still new to the blockchain codes. This helps me clarify a lot!

I changed to send({from:account, gas: '25000000000'}). Now it's showing error:

------- results:  Error: Returned error: unknown account

Do you have any insights on where that's coming from?

jimni1222 commented 4 years ago

You should add account to in-memory wallet! You can add an account via caver.klay.accounts.wallet.add(https://docs.klaytn.com/bapp/sdk/caver-js/v1.4.1/api-references/caver.klay.accounts#wallet-add).

zjj010104 commented 4 years ago

Got it! I can send properly now! Thank you very much!

kjhman21 commented 4 years ago

@zjj010104 Next time, please use https://forum.klaytn.com/c/caver/caver-english/7 for questions related to caver-js. You can also find other QnAs for Klaytn. Thanks.