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");