web3p / web3.php

A php interface for interacting with the Ethereum blockchain and ecosystem. Native ABI parsing and smart contract interactions.
MIT License
1.17k stars 550 forks source link

execution reverted #251

Open vnxz opened 2 years ago

vnxz commented 2 years ago

I try to transfer token to another account by laravel. error is

execution reverted 

here is code


class Web3Controller extends Controller
{
       public function web3() {

$abi = json_decode('[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"tokens","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"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":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"_totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"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":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeSub","outputs":[{"name":"c","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeDiv","outputs":[{"name":"c","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"tokens","type":"uint256"},{"name":"data","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeMul","outputs":[{"name":"c","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"newOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"tokenAddress","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transferAnyERC20Token","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256"}],"name":"safeAdd","outputs":[{"name":"c","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tokenOwner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Approval","type":"event"}]');

$Bytecode = '0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061044f806100606000396000f300608060405260043610610062576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063075461721461006757806327e235e3146100be57806340c10f1914610115578063d0679d3414610162575b600080fd5b34801561007357600080fd5b5061007c6101af565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100ca57600080fd5b506100ff600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506101d4565b6040518082815260200191505060405180910390f35b34801561012157600080fd5b50610160600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506101ec565b005b34801561016e57600080fd5b506101ad600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610299565b005b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60016020528060005260406000206000915090505481565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561024757610295565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505b5050565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156102e55761041f565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055507f3990db2d31862302a685e8086b5755072a6e2b5b780af1ee81ece35ee3cd3345338383604051808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001828152602001935050505060405180910390a15b50505600a165627a7a723058202be9622eb5a1e1d65451a0b954cc9409897c128df0806b66df54e387effd9c060029';

$contract = new Contract('https://ropsten.infura.io/v3/34bc013ca1124ee0af5004bfd1cfc454', $abi);

$contractAddress = '0x64Ababe58B9e195d20533F092C13CFaAD4143211';

$accountaddress = '0xeE01EDe04D42e1a51C99f2737B9E14Fc930a1fd4';
$toaddress ='0x5a86f0cafd4ef3ba4f0344c138afcc84bd1ed222';
$amount = 10;
    // call contract function

// $contract->at($contractAddress)

//              ->call('balanceOf', $accountaddress , function ($err, $data) {
//                if ($err !== null) {
//                  throw new Exception($err->getMessage());
//                }
//                dd($data);
//              });

$contract->at($contractAddress)
          ->call('transfer', $toaddress ,$amount , function ($err, $data) {
                if ($err !== null) {
                  throw new Exception($err->getMessage());
                }
                dd($data);
              });

   }

}

here is smart contract

pragma solidity ^0.4.24;

// ----------------------------------------------------------------------------
// 'Cryptnet' token contract
//
// Deployed to : 0xeE01EDe04D42e1a51C99f2737B9E14Fc930a1fd4
// Symbol      : CN
// Name        : Cryptnet Token
// Total supply: 100000000
// Decimals    : 18
//
// Enjoy.
//
// (c) by Moritz Neto with BokkyPooBah / Bok Consulting Pty Ltd Au 2017. The MIT Licence.
// ----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// Safe maths
// ----------------------------------------------------------------------------
contract SafeMath {
    function safeAdd(uint a, uint b) public pure returns (uint c) {
        c = a + b;
        require(c >= a);
    }
    function safeSub(uint a, uint b) public pure returns (uint c) {
        require(b <= a);
        c = a - b;
    }
    function safeMul(uint a, uint b) public pure returns (uint c) {
        c = a * b;
        require(a == 0 || c / a == b);
    }
    function safeDiv(uint a, uint b) public pure returns (uint c) {
        require(b > 0);
        c = a / b;
    }
}

// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
    function totalSupply() public constant returns (uint);
    function balanceOf(address tokenOwner) public constant returns (uint balance);
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);

    event Transfer(address indexed from, address indexed to, uint tokens);
    event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}

// ----------------------------------------------------------------------------
// Contract function to receive approval and execute function in one call
//
// Borrowed from MiniMeToken
// ----------------------------------------------------------------------------
contract ApproveAndCallFallBack {
    function receiveApproval(address from, uint256 tokens, address token, bytes data) public;
}

// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Owned {
    address public owner;
    address public newOwner;

    event OwnershipTransferred(address indexed _from, address indexed _to);

    constructor() public {
        owner = msg.sender;
    }

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    function transferOwnership(address _newOwner) public onlyOwner {
        newOwner = _newOwner;
    }
    function acceptOwnership() public {
        require(msg.sender == newOwner);
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
        newOwner = address(0);
    }
}

// ----------------------------------------------------------------------------
// ERC20 Token, with the addition of symbol, name and decimals and assisted
// token transfers
// ----------------------------------------------------------------------------
contract CryptnetToken is ERC20Interface, Owned, SafeMath {
    string public symbol;
    string public  name;
    uint8 public decimals;
    uint public _totalSupply;

    mapping(address => uint) balances;
    mapping(address => mapping(address => uint)) allowed;

    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------
    constructor() public {
        symbol = "CN";
        name = "Cryptnet Token";
        decimals = 18;
        _totalSupply = 100000000000000000000000000;
        balances[0xeE01EDe04D42e1a51C99f2737B9E14Fc930a1fd4] = _totalSupply;
        emit Transfer(address(0), 0xeE01EDe04D42e1a51C99f2737B9E14Fc930a1fd4, _totalSupply);
    }

    // ------------------------------------------------------------------------
    // Total supply
    // ------------------------------------------------------------------------
    function totalSupply() public constant returns (uint) {
        return _totalSupply  - balances[address(0)];
    }

    // ------------------------------------------------------------------------
    // Get the token balance for account tokenOwner
    // ------------------------------------------------------------------------
    function balanceOf(address tokenOwner) public constant returns (uint balance) {
        return balances[tokenOwner];
    }

    // ------------------------------------------------------------------------
    // Transfer the balance from token owner's account to to account
    // - Owner's account must have sufficient balance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transfer(address to, uint tokens) public returns (bool success) {
        balances[msg.sender] = safeSub(balances[msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(msg.sender, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account
    //
    // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
    // recommends that there are no checks for the approval double-spend attack
    // as this should be implemented in user interfaces 
    // ------------------------------------------------------------------------
    function approve(address spender, uint tokens) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Transfer tokens from the from account to the to account
    // 
    // The calling account must already have sufficient tokens approve(...)-d
    // for spending from the from account and
    // - From account must have sufficient balance to transfer
    // - Spender must have sufficient allowance to transfer
    // - 0 value transfers are allowed
    // ------------------------------------------------------------------------
    function transferFrom(address from, address to, uint tokens) public returns (bool success) {
        balances[from] = safeSub(balances[from], tokens);
        allowed[from][msg.sender] = safeSub(allowed[from][msg.sender], tokens);
        balances[to] = safeAdd(balances[to], tokens);
        emit Transfer(from, to, tokens);
        return true;
    }

    // ------------------------------------------------------------------------
    // Returns the amount of tokens approved by the owner that can be
    // transferred to the spender's account
    // ------------------------------------------------------------------------
    function allowance(address tokenOwner, address spender) public constant returns (uint remaining) {
        return allowed[tokenOwner][spender];
    }

    // ------------------------------------------------------------------------
    // Token owner can approve for spender to transferFrom(...) tokens
    // from the token owner's account. The spender contract function
    // receiveApproval(...) is then executed
    // ------------------------------------------------------------------------
    function approveAndCall(address spender, uint tokens, bytes data) public returns (bool success) {
        allowed[msg.sender][spender] = tokens;
        emit Approval(msg.sender, spender, tokens);
        ApproveAndCallFallBack(spender).receiveApproval(msg.sender, tokens, this, data);
        return true;
    }

    // ------------------------------------------------------------------------
    // Don't accept ETH
    // ------------------------------------------------------------------------
    function () public payable {
        revert();
    }

    // ------------------------------------------------------------------------
    // Owner can transfer out any accidentally sent ERC20 tokens
    // ------------------------------------------------------------------------
    function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool success) {
        return ERC20Interface(tokenAddress).transfer(owner, tokens);
    }
}

may be due to cannot call directly transfer method ? or what? can someone explain me how can call contract method by laravel for this contract.

jose5958 commented 2 years ago

Hello, you should sign your transaction before sending it, refer to this link, there is an example: https://github.com/web3p/web3.php/issues/216

MariusMez commented 2 years ago

Here is a full example how to call a function on a smart contract which require a signer (to change the status of the blockchain). A simple call like balanceOf function doesn't require a signer so thats why it's working, but when you need to change content, you need to sign the transaction before like @jose5958 wrote before.

Assuming below:

And also this code require the use of an other package from the same author : https://github.com/web3p/ethereum-tx It is used to send raw transaction with signer

public function transferMyGreatToken($recipientAccount, $quantity): mixed
    {
        Log::debug("Call {$quantity} transferMyGreatToken for recipient={$recipientAccount}");

        $transactionCount = null;
        $this->contract->eth->getTransactionCount($this->ownerAccount, function ($err, $transactionCountResult) use(&$transactionCount) {
            if($err) {
                Log::error('getTransactionCount error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $transactionCount = $transactionCountResult;
        });
        Log::debug("transactionCount=$transactionCount");

        $gasPrice = null;
        $this->contract->eth->gasPrice(function ($err, $gasPriceResult) use(&$gasPrice) {
            if($err) {
                Log::error('gasPrice error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $gasPrice = $gasPriceResult;
        });
        Log::debug("gasPrice=$gasPrice");

        $rawTransactionData = '0x' . $this->contract->getData('transferMyGreatToken', $recipientAccount, $quantity);

        $transactionParams = [
            'nonce' => "0x" . dechex($transactionCount->toString()),
            'from' => $this->ownerAccount,
            'to' =>  $this->contractAddress,
            'gasPrice' =>  '0x' . hexdec(dechex($gasPrice->toString())),
            'value' => '0x0',
            'data' => $rawTransactionData
        ];

        $estimatedGas = null;
        $this->contract->eth->estimateGas($transactionParams, function ($err, $gas) use (&$estimatedGas) {
            if ($err) {
                Log::error('estimateGas error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $estimatedGas = $gas;
        });
        Log::debug("estimatedGas=$estimatedGas");

        $gasPriceLimit = $this->computeGasLimit($estimatedGas);

        $transactionParams['gasLimit'] = '0x' . dechex($gasPriceLimit);
        $transactionParams['chainId'] = $this->chainId;

        $tp = json_encode($transactionParams);
        Log::debug("transactionParams=$tp");

        $tx = new Web3Transaction($transactionParams);
        $signedTx = '0x' . $tx->sign($this->ownerPKey);
        $txHash = null;
        $this->contract->eth->sendRawTransaction($signedTx, function ($err, $txResult) use (&$txHash) {
            if($err) {
                Log::error('transaction error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $txHash = $txResult;
        });
        Log::debug("txHash=$txHash");

        $txReceipt = null;
        Log::debug("Waiting for transaction receipt");
        for ($i=0; $i <= $this->secondsToWaitForReceipt; $i++) {
            $this->contract->eth->getTransactionReceipt($txHash, function ($err, $txReceiptResult) use(&$txReceipt) {
                if($err) {
                    Log::error('getTransactionReceipt error: ' . $err->getMessage());
                    throw new RuntimeException($err->getMessage());
                }
                $txReceipt = $txReceiptResult;
            });
            if ($txReceipt) {
                break;
            }
            sleep(1);
        }
        $txStatus = $txReceipt->status;
        Log::debug("txStatus=$txStatus");

        return $txStatus;
    }
banls commented 2 years ago

$this->contract->getData is not function

banls commented 2 years ago

what this ???????????????????????

aminesmkhani commented 2 years ago

@MariusMez

what is $this->chainId value?!

MariusMez commented 2 years ago

The chainId of the blockchain you are using...

// See: https://chainlist.org

  public const chainIds = [
      'mainnet' => 1,
      'ropsten' => 3,
      'rinkeby' => 4,
      'goerli' => 5,
      'kovan' => 42,
      'mumbai' => 80001,
      'polygon_testnet' => 80001,
      'polygon' => 137,
      'matic' => 137,
  ];
aminesmkhani commented 2 years ago

@MariusMez

Thanks for the reply

another question

‍‍ $this->computeGasLimit $this->secondsToWaitForReceipt

What does it calculate! I know what it is but I do not know how :)

If you have a sample code, thank you for sharing

MariusMez commented 2 years ago

Indeed, I didn't remove this optional part. In fact this method use an empiric way to define the maximum gas limit to use:

/**
   * Compute the maximum gasLimit value to use for a transaction
   * TODO: think of a better way to handle this 
   * @param $estimatedGas
   * @return int
   */
  public function computeGasLimit($estimatedGas): int
  {
      $maxGasLimit = (int) config('web3.max_gas_limit', 15000000);
      $factorToMultiplyGasEstimate = (int) config('web3.factor_to_multiply_gas_estimate');
      $gasPriceLimit = hexdec(dechex($estimatedGas->toString())) * $factorToMultiplyGasEstimate;
      if ($gasPriceLimit > $maxGasLimit) {
          $gasPriceLimit = $maxGasLimit;
      }
      Log::debug("gasPriceLimit=$gasPriceLimit");
      return $gasPriceLimit;
  }

And $this->secondsToWaitForReceipt is a timeout you have to set (20s/30s)

banjjara commented 2 years ago

Here is a full example how to call a function on a smart contract which require a signer (to change the status of the blockchain). A simple call like balanceOf function doesn't require a signer so thats why it's working, but when you need to change content, you need to sign the transaction before like @jose5958 wrote before.

Assuming below:

  • $this->contract = new Contract($provider, $abi);
  • $this->ownerAccount = address of contract owner
  • $this->ownerPKey = private key of the contract owner used to sign the transaction

And also this code require the use of an other package from the same author : https://github.com/web3p/ethereum-tx It is used to send raw transaction with signer

public function transferMyGreatToken($recipientAccount, $quantity): mixed
    {
        Log::debug("Call {$quantity} transferMyGreatToken for recipient={$recipientAccount}");

        $transactionCount = null;
        $this->contract->eth->getTransactionCount($this->ownerAccount, function ($err, $transactionCountResult) use(&$transactionCount) {
            if($err) {
                Log::error('getTransactionCount error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $transactionCount = $transactionCountResult;
        });
        Log::debug("transactionCount=$transactionCount");

        $gasPrice = null;
        $this->contract->eth->gasPrice(function ($err, $gasPriceResult) use(&$gasPrice) {
            if($err) {
                Log::error('gasPrice error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $gasPrice = $gasPriceResult;
        });
        Log::debug("gasPrice=$gasPrice");

        $rawTransactionData = '0x' . $this->contract->getData('transferMyGreatToken', $recipientAccount, $quantity);

        $transactionParams = [
            'nonce' => "0x" . dechex($transactionCount->toString()),
            'from' => $this->ownerAccount,
            'to' =>  $this->contractAddress,
            'gasPrice' =>  '0x' . hexdec(dechex($gasPrice->toString())),
            'value' => '0x0',
            'data' => $rawTransactionData
        ];

        $estimatedGas = null;
        $this->contract->eth->estimateGas($transactionParams, function ($err, $gas) use (&$estimatedGas) {
            if ($err) {
                Log::error('estimateGas error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $estimatedGas = $gas;
        });
        Log::debug("estimatedGas=$estimatedGas");

        $gasPriceLimit = $this->computeGasLimit($estimatedGas);

        $transactionParams['gasLimit'] = '0x' . dechex($gasPriceLimit);
        $transactionParams['chainId'] = $this->chainId;

        $tp = json_encode($transactionParams);
        Log::debug("transactionParams=$tp");

        $tx = new Web3Transaction($transactionParams);
        $signedTx = '0x' . $tx->sign($this->ownerPKey);
        $txHash = null;
        $this->contract->eth->sendRawTransaction($signedTx, function ($err, $txResult) use (&$txHash) {
            if($err) {
                Log::error('transaction error: ' . $err->getMessage());
                throw new RuntimeException($err->getMessage());
            }
            $txHash = $txResult;
        });
        Log::debug("txHash=$txHash");

        $txReceipt = null;
        Log::debug("Waiting for transaction receipt");
        for ($i=0; $i <= $this->secondsToWaitForReceipt; $i++) {
            $this->contract->eth->getTransactionReceipt($txHash, function ($err, $txReceiptResult) use(&$txReceipt) {
                if($err) {
                    Log::error('getTransactionReceipt error: ' . $err->getMessage());
                    throw new RuntimeException($err->getMessage());
                }
                $txReceipt = $txReceiptResult;
            });
            if ($txReceipt) {
                break;
            }
            sleep(1);
        }
        $txStatus = $txReceipt->status;
        Log::debug("txStatus=$txStatus");

        return $txStatus;
    }

i m trying to understand this in plane php but i m stuck on this line $rawTransactionData = '0x' . $this->contract->getData('transferMyGreatToken', $recipientAccount, $quantity);

what is TransferMyGreateToken can i have this in base php please thanks for you help guidance you providing here

MariusMez commented 2 years ago

It's the name of the smart contract method you want to call. For example purpose I choose 'transferMyGreatToken', but of course you need to change it. (For a specific smart contract wich is not yours, you can find all methods/function names and event in the smart contract ABI)

banjjara commented 2 years ago

It's the name of the smart contract method you want to call. For example purpose I choose 'transferMyGreatToken', but of course you need to change it. (For a specific smart contract wich is not yours, you can find all methods/function names and event in the smart contract ABI)

this is the code i m trying to run $rawTransactionData = '0x' . $my_contract->getData("transferFrom", $ownerAccount, $toAccount, $quantity);

here is smart contract method function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); return true; }

and here is abi $contract_abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TokenPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_airdrop","type":"uint256"}],"name":"setDrop","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rate","outputs":[{"name":"","type":"uint256"}],"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":"airdrop","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"airdropTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_rate","type":"uint256"}],"name":"setPrice","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isMinter","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_rewards","type":"uint256"}],"name":"setRewards","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"buyTokens","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_initialSupply","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]';

but i m getting error Fatal error: Uncaught InvalidArgumentException: Please make sure you have put all function params and callback. in /var/www/web3/vendor/sc0vu/web3.php/src/Contract.php:561 Stack trace: #0 /var/www/web3/sendtoken.php(96): Web3\Contract->send() #1 {main} thrown in /var/www/web3/vendor/sc0vu/web3.php/src/Contract.php on line 561

banjjara commented 2 years ago

It's the name of the smart contract method you want to call. For example purpose I choose 'transferMyGreatToken', but of course you need to change it. (For a specific smart contract wich is not yours, you can find all methods/function names and event in the smart contract ABI)

this is the code i m trying to run $rawTransactionData = '0x' . $my_contract->getData("transferFrom", $ownerAccount, $toAccount, $quantity);

here is smart contract method function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "BEP20: transfer amount exceeds allowance")); return true; }

and here is abi $contract_abi = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"TokenPrice","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_airdrop","type":"uint256"}],"name":"setDrop","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rate","outputs":[{"name":"","type":"uint256"}],"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":"airdrop","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"name":"mint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"airdropTokens","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_rate","type":"uint256"}],"name":"setPrice","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"account","type":"address"}],"name":"addMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceMinter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewards","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isMinter","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_rewards","type":"uint256"}],"name":"setRewards","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"buyTokens","outputs":[{"name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_initialSupply","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"account","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]';

but i m getting error Fatal error: Uncaught InvalidArgumentException: Please make sure you have put all function params and callback. in /var/www/web3/vendor/sc0vu/web3.php/src/Contract.php:561 Stack trace: #0 /var/www/web3/sendtoken.php(96): Web3\Contract->send() #1 {main} thrown in /var/www/web3/vendor/sc0vu/web3.php/src/Contract.php on line 561

any help guys please how can i send token using base php with this library

amonit commented 1 year ago

did you found a solution?