ABI stands for application binary interface, it is the standard way to interact with contracts in the Ethereum ecosystem, both from outside the blockchain and for contract-to-contract interaction.
Data is encoded or decoded according to its type.
<?php use kornrunner\Keccak; use Web3\Contracts\Types\{Address, Boolean, Bytes, DynamicBytes, Integer, Str, Uinteger}; use Web3\Contracts\Ethabi; use Web3\Utils; include_once "../libraries/vendor/autoload.php"; $ethAbi = new Ethabi(['address' => new Address,'bool' => new Boolean,'bytes' => new Bytes,'dynamicBytes' => new DynamicBytes,'int' => new Integer,'string' => new Str,'uint' => new Uinteger,]); $hosts = ["https://mainnet.infura.io"=>"https://mainnet.infura.io","https://goerli.infura.io"=>"https://goerli.infura.io", "https://cloudflare-eth.com"=>"https://cloudflare-eth.com", "https://eth-mainnet.alchemyapi.io"=>"https://eth-mainnet.alchemyapi.io", "https://eth-ropsten.alchemyapi.io"=>"https://eth-ropsten.alchemyapi.io", "https://testnet-rpc.anisticnetwork.net"=>"https://testnet-rpc.anisticnetwork.net", "https://data-seed-prebsc-1-s2.binance.org:8545"=>"https://data-seed-prebsc-1-s2.binance.org:8545"]; if ($_SERVER['REQUEST_METHOD'] == 'POST') { $ajaxData = []; if ($_GET['action'] == 'parse_abi' OR ($_GET['action'] == 'submit' AND isset($_POST['abi']))) { $ajaxData['functions'] = []; $blocks = json_decode($_POST['abi'], true); if (@count($blocks) > 0) { foreach($blocks as $block) { if ($block['type'] == 'function') { $ajaxData['functions'][] = $block['name']; } } } else { $errmsg .= "Invalid ABI."; } if ($_GET['ajax'] == '1') { if ($errmsg) { $ajaxData['error'] = $errmsg; } die(json_encode($ajaxData)); } } if ($_GET['action'] == 'get_args' OR ($_GET['action'] == 'submit' AND isset($_POST['abi']) AND isset($_POST['function'])) ) { $ajaxData['args'] = []; $blocks = json_decode($_POST['abi'], true); if (@count($blocks) > 0) { foreach($blocks as $block) { if ($block['type'] == 'function' and $block['name'] == $_POST['function']) { if ($block['inputs']) { foreach($block['inputs'] as $input) { $ajaxData['args'][] = $input['name'] . " ({$input['type']})"; } } } } } if ($_GET['ajax'] == '1') { if ($errmsg) { $ajaxData['error'] = $errmsg; } die(json_encode($ajaxData)); } } } include_once("html_iframe_header.php"); if ($_SERVER['REQUEST_METHOD'] == 'POST') { try { if (!$_POST['function']) { throw new Exception("Function should not be blank."); } $_POST['args'] = is_array($_POST['args']) ? $_POST['args'] : []; $blocks = json_decode($_POST['abi'], true); $data = ""; if (@count($blocks) > 0) { foreach($blocks as $block) { if ($block['type'] == 'function' and $block['name'] == $_POST['function']) { $encoded = ""; if ($block['inputs']) { $params = $values = []; foreach($block['inputs'] as $k => $input) { $params[] = $input['type']; if (substr($input['type'],-2) == "[]") { $values[] = json_decode($_POST['args'][$k],true); } else { $values[] = $_POST['args'][$k]; } } $encoded = substr($ethAbi->encodeParameters($params, $values),2); //remove 0x prefix } $methodStr = Utils::jsonMethodToString($block); $data = $ethAbi->encodeFunctionSignature($methodStr).$encoded ; break; } } } ?> <div class="alert alert-success"> <h6 class="mt-3">Data (Hex)</h6> <textarea class="form-control" rows="5" id="comment" readonly><?php echo $data;?></textarea> </div> <?php } catch (Exception $e) { $errmsg .= "Problem found. " . $e->getMessage(); } } if ($errmsg) { ?> <div class="alert alert-danger"> <strong>Error!</strong> <?php echo $errmsg?> </div> <?php } ?> <form id='this_form' action='?action=submit' method='post'> <div class="form-group"> <label for="function">Function:</label> <select class="form-control" type='text' name='function' id='function' value='<?php echo $_POST['function']?>' onchange=" var self = $(this); var form = self.closest('form'); $('p#args_panel',form).empty(); $('p#args_panel',form).html(''); $.ajax({ url: '?ajax=1&action=get_args', type: 'post', data: $('#this_form :input'), success:function(result){ try { j = eval('(' + result + ')'); if ('error' in j && j.error.length>0) { var error = true; } else { var error = false; } if (!error) { var args = j.args; if (args.length > 0) { var x; for (x in args) { $('p#args_panel',form).append('<div class=\'form-group\'>'+ args[x] +':<input class=\'form-control\' type=\'text\' name=\'args[]\'/></div>'); } } else { $('p#args_panel',form).html(' No arguments'); } } else { alert(j.error); } } catch(e) { alert('Invalid Json Format.'); } }, complete:function() { } }); "> <?php if (@count($ajaxData['functions']) > 0) { ?> <option value=''>Please select ...</option> <?php foreach($ajaxData['functions'] as $function_name) { $optionSelected = $function_name == $_POST['function'] ? " selected='selected'" : ""; ?> <option value='<?php echo $function_name?>'<?php echo $optionSelected?>><?php echo $function_name?></option> <?php } } else { ?> <option value="">Please load from ABI ...</option> <?php } ?> </select> </div> <div class="form-group"> <label for="args">Function Arguments:</label> <p id='args_panel'> </p> </div> <div class="form-group"> <label for="gas_price">ABI:</label> <div class="input-group mb-3"> <textarea class="form-control" rows="10" name='abi' id='abi'><?php echo $_POST['abi']?></textarea> <div class="input-group-append"> <input class="btn btn-success" type="button" value="Load" onclick=" var self = $(this); self.val('...'); var form = self.closest('form'); $('select#function',form).empty(); $.ajax({ url: '?ajax=1&action=parse_abi', type: 'post', data: $('#this_form :input'), success:function(result){ try { j = eval('(' + result + ')'); if ('error' in j && j.error.length>0) { var error = true; } else { var error = false; } if (!error) { var functions = j.functions; if (functions.length > 0) { $('select#function',form).append('<option value=\'\' selected=\'selected\'>Please select ...</option>'); var x; for (x in functions) { $('select#function',form).append('<option value=\''+functions[x]+'\'>'+functions[x]+'</option>'); } } } else { $('select#function',form).prepend('<option value=\'\' selected=\'selected\'>Please load from ABI ...</option>'); alert(j.error); } } catch(e) { $('select#function',form).prepend('<option value=\'\' selected=\'selected\'>Please load from ABI ...</option>'); alert('Invalid Json Format.'); } }, complete:function() { self.val('Load'); } }); "/> </div> </div> </div> <input type='submit' class="btn btn-success btn-block"/> </form> <script> <?php if ($_GET['action'] == 'submit') { if (@count($ajaxData['args']) > 0) { foreach($ajaxData['args'] as $k=>$arg) { ?> $('p#args_panel').append('<div class=\'form-group\'><?php echo $arg?>:<input class=\'form-control\' type=\'text\' name=\'args[]\' value=\'<?php echo $_POST['args'][$k]?>\'/></div>'); <?php } } else { ?> $('p#args_panel').html(' No arguments'); <?php } } ?> </script> <?php include_once("html_iframe_footer.php");
<?php use Web3\Contracts\Ethabi; use Web3\Contracts\Types\{Address, Boolean, Bytes, DynamicBytes, Integer, Str, Uinteger}; include_once "../libraries/vendor/autoload.php"; $ethAbi = new Ethabi(['address' => new Address,'bool' => new Boolean,'bytes' => new Bytes,'dynamicBytes' => new DynamicBytes,'int' => new Integer,'string' => new Str,'uint' => new Uinteger,]); if ($_SERVER['REQUEST_METHOD'] == 'POST') { $ajaxData = []; if ($_GET['action'] == 'parse_abi' OR ($_GET['action'] == 'submit' AND isset($_POST['abi']))) { $ajaxData['functions'] = []; $abiBlocks = json_decode($_POST['abi'], true); if (@count($abiBlocks) > 0) { foreach($abiBlocks as $abiBlock) { if ($abiBlock['type'] == 'function') { if (count($abiBlock['outputs']) > 0) { $ajaxData['functions'][] = $abiBlock['name']; } } } } else { $errmsg .= "Invalid ABI."; } if ($_GET['ajax'] == '1') { if ($errmsg) { $ajaxData['error'] = $errmsg; } die(json_encode($ajaxData)); } } } include_once("html_iframe_header.php"); $results = []; if ($_SERVER['REQUEST_METHOD'] == 'POST') { try { if (!$_POST['function'] OR !$_POST['abi']) { throw new Exception("Abi with selected function is needed."); } $abiBlocks = json_decode($_POST['abi'], true); if (@count($abiBlocks) > 0) { foreach($abiBlocks as $abiBlock) { if ($abiBlock['type'] == 'function' and $abiBlock['name'] == $_POST['function']) { $totalOutputs = count($abiBlock['outputs']); if ($totalOutputs) { $encoded = $_POST['response']; // Remove 0x prefix if (substr($encoded, 0, 2) === '0x') { $encoded = substr($encoded, 2); } if (strlen($encoded) != 64 * $totalOutputs) { throw new Exception("Response length is not valid."); } $decodeds = str_split($encoded, 64); foreach($decodeds as $k=> $decoded) { $result['name'] = $abiBlock['outputs'][$k]['name']; $result['type'] = $abiBlock['outputs'][$k]['type']; $result['hex'] = "0x". $decoded; $result['value'] = $ethAbi->decodeParameter($abiBlock['outputs'][$k]['type'], $decoded); $results[] = $result; } } } } } ?> <div class="alert alert-success"> <?php echo $totalOutputs?> outputs have been decoded. </div> <div class="table-responsive"> <table class="table table-bordered"> <tr><th>Name</th><th>Type</th><th>Hex</th><th>Decoded Value</th></tr> <?php foreach($results as $result) { ?> <tr> <td><?Php echo $result['name']?></td> <td><?Php echo $result['type']?></td> <td><?Php echo $result['hex']?></td> <td><?Php echo $result['value']?></td> </tr> <?Php } ?> </table> </div> <?php } catch (Exception $e) { $errmsg .= "Problem found. " . $e->getMessage(); } } if ($errmsg) { ?> <div class="alert alert-danger"> <strong>Error!</strong> <?php echo $errmsg?> </div> <?php } ?> <form id='this_form' action='?action=submit' method='post'> <div class="form-group"> <label for="response">Response To Decode:</label> <input class="form-control" type='text' name='response' id='response' value='<?php echo $_POST['response']?>'> <small>You may get this response from <a href="eth_call.php" target='_blank'>Ethereum Eth Call</a> to decode.</small> </div> <div class="form-group"> <label for="function">Function:</label> <select class="form-control" type='text' name='function' id='function' value='<?php echo $_POST['function']?>'> <?php if (@count($ajaxData['functions']) > 0) { ?> <option value=''>Please select ...</option> <?php foreach($ajaxData['functions'] as $function_name) { $optionSelected = $function_name == $_POST['function'] ? " selected='selected'" : ""; ?> <option value='<?php echo $function_name?>'<?php echo $optionSelected?>><?php echo $function_name?></option> <?php } } else { ?> <option value="">Please load from ABI ...</option> <?php } ?> </select> </div> <div class="form-group"> <label for="gas_price">ABI:</label> <div class="input-group mb-3"> <textarea class="form-control" rows="10" name='abi' id='abi'><?php echo $_POST['abi']?></textarea> <div class="input-group-append"> <input class="btn btn-success" type="button" value="Load" onclick=" var self = $(this); self.val('...'); var form = self.closest('form'); $('select#function',form).empty(); $.ajax({ url: '?ajax=1&action=parse_abi', type: 'post', data: $('#this_form :input'), success:function(result){ try { j = eval('(' + result + ')'); if ('error' in j && j.error.length>0) { var error = true; } else { var error = false; } if (!error) { var functions = j.functions; if (functions.length > 0) { $('select#function',form).append('<option value=\'\' selected=\'selected\'>Please select ...</option>'); var x; for (x in functions) { $('select#function',form).append('<option value=\''+functions[x]+'\'>'+functions[x]+'</option>'); } } } else { $('select#function',form).prepend('<option value=\'\' selected=\'selected\'>Please load from ABI ...</option>'); alert(j.error); } } catch(e) { $('select#function',form).prepend('<option value=\'\' selected=\'selected\'>Please load from ABI ...</option>'); alert('Invalid Json Format.'); } }, complete:function() { self.val('Load'); } }); "/> </div> </div> </div> <input type='submit' class="btn btn-success btn-block"/> </form> <?php include_once("html_iframe_footer.php");