This commit is contained in:
T.T 2022-08-25 04:50:43 +00:00 committed by GitHub
commit f3c5751057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 203 additions and 1 deletions

View File

@ -32,6 +32,7 @@ use Web3\Validators\StringValidator;
use Web3\Validators\TagValidator;
use Web3\Validators\QuantityValidator;
use Web3\Formatters\AddressFormatter;
use Web3\Contracts\Types\Tuple;
class Contract
{
@ -162,6 +163,7 @@ class Contract
'int' => new Integer,
'string' => new Str,
'uint' => new Uinteger,
'tuple' => new Tuple,
]);
}

View File

@ -238,9 +238,13 @@ class Ethabi
if (isset($outputTypes['outputs'][$i]['name']) && empty($outputTypes['outputs'][$i]['name']) === false) {
$result[$outputTypes['outputs'][$i]['name']] = $solidityTypes[$i]->decode($param, $offsets[$i], $types[$i]);
} else {
if($types[$i] == "tuple"){
$result[$i] = $solidityTypes[$i]->decodeTuple($outputTypes['outputs'][$i],$param);
}else{
$result[$i] = $solidityTypes[$i]->decode($param, $offsets[$i], $types[$i]);
}
}
}
return $result;
}

View File

@ -13,9 +13,21 @@ namespace Web3\Contracts;
use Web3\Utils;
use Web3\Formatters\IntegerFormatter;
use InvalidArgumentException;
use Web3\Contracts\Types\Address;
use Web3\Contracts\Types\Boolean;
use Web3\Contracts\Types\Bytes;
use Web3\Contracts\Types\DynamicBytes;
use Web3\Contracts\Types\Integer;
use Web3\Contracts\Types\Str;
use Web3\Contracts\Types\Uinteger;
use Web3\Contracts\Types\Tuple;
class SolidityType
{
private array $types = [];
/**
* construct
*
@ -23,6 +35,27 @@ class SolidityType
*/
// public function __construct() {}
/**
* set types
*/
private function setTypes()
{
if(!empty($this->types)){
return $this->types;
}
$this->types = [
'address' => new Address,
'bool' => new Boolean,
'bytes' => new Bytes,
'dynamicBytes' => new DynamicBytes,
'int' => new Integer,
'string' => new Str,
'uint' => new Uinteger,
'tuple' => new Tuple,
];
return $this->types;
}
/**
* get
*
@ -270,4 +303,81 @@ class SolidityType
return $this->outputFormat($param, $name);
}
/**
* decode struct data
*
* @author abaowu <abaowu@gmail.com>
* @param array $type tuple struct
* @param mix $value tuple value
* @return array
*/
public function decodeTuple($type, $value)
{
$outputTypes = $type["components"];
$typesLength = count($outputTypes);
$solidityTypes = $this->getSolidityTypes($outputTypes);
$offsets = array_fill(0, $typesLength, 0);
for ($i=0; $i<$typesLength; $i++) {
$offsets[$i] = $solidityTypes[$i]->staticPartLength($outputTypes[$i]['type']);
}
for ($i=1; $i<$typesLength; $i++) {
$offsets[$i] += $offsets[$i - 1];
}
for ($i=0; $i<$typesLength; $i++) {
$offsets[$i] -= $solidityTypes[$i]->staticPartLength($outputTypes[$i]['type']);
}
$result = [];
$param = mb_strtolower(Utils::stripZero($value));
for ($i=0; $i<$typesLength; $i++) {
if (isset($outputTypes[$i]['name']) && empty($outputTypes[$i]['name']) === false) {
$result[$outputTypes[$i]['name']] = $solidityTypes[$i]->decode($param, $offsets[$i], $outputTypes[$i]['type']);
} else {
$result[$i] = $solidityTypes[$i]->decode($param, $offsets[$i], $outputTypes[$i]['type']);
}
}
return $result;
}
/**
* getSolidityTypes
*
* @param array $types
* @return array
*/
protected function getSolidityTypes($types)
{
if (!is_array($types)) {
throw new InvalidArgumentException('Types must be array');
}
$solidityTypes = array_fill(0, count($types), 0);
$this->setTypes();
foreach ($types as $key => $type) {
$match = [];
$type = $type['type'];
if (preg_match('/^([a-zA-Z]+)/', $type, $match) === 1) {
if (isset($this->types[$match[0]])) {
$className = $this->types[$match[0]];
if (call_user_func([$this->types[$match[0]], 'isType'], $type) === false) {
// check dynamic bytes
if ($match[0] === 'bytes') {
$className = $this->types['dynamicBytes'];
} else {
throw new InvalidArgumentException('Unsupport solidity parameter type: ' . $type);
}
}
$solidityTypes[$key] = $className;
}
}
}
return $solidityTypes;
}
}

View File

@ -0,0 +1,86 @@
<?php
/**
* This file is part of web3.php package.
*
* (c) abaowu <abaowu@gmail.com>
*
* @author abaowu <abaowu@gmail.com>
* @license MIT
*/
namespace Web3\Contracts\Types;
use Web3\Contracts\SolidityType;
use Web3\Contracts\Types\IType;
class Tuple extends SolidityType implements IType
{
/**
* construct
*
* @return void
*/
public function __construct()
{
//
}
/**
* isType
*
* @param string $name
* @return bool
*/
public function isType($name)
{
return (preg_match('/^tuple(\[([0-9]*)\])*$/', $name) === 1);
}
/**
* isDynamicType
*
* @return bool
*/
public function isDynamicType()
{
return true;
}
/**
* inputFormat
* to do: iban
*
* @param mixed $value
* @param string $name
* @return string
*/
public function inputFormat($value, $name)
{
// $value = (string) $value;
// if (Utils::isAddress($value)) {
// $value = mb_strtolower($value);
// if (Utils::isZeroPrefixed($value)) {
// $value = Utils::stripZero($value);
// }
// }
// $value = IntegerFormatter::format($value);
return $value;
}
/**
* outputFormat
*
* @param mixed $value
* @param string $name
* @return string
*/
public function outputFormat($value, $name)
{
// return '0x' . mb_substr($value, 24, 40);
return $value;
}
}