Blockchain-Ethereum

 view release on metacpan or  search on metacpan

lib/Blockchain/Ethereum/ABI/Decoder.pm  view on Meta::CPAN

Decodes appended signatures

Usage:

    decode() -> []

=over 4

=back

Returns an array reference containing all decoded values

=head1 AUTHOR

REFECO <refeco@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is Copyright (c) 2022 by REFECO.

This is free software, licensed under:

lib/Blockchain/Ethereum/Keystore/Keyfile.pm  view on Meta::CPAN

}

sub _json {
    return shift->{json} //= JSON::MaybeXS->new(utf8 => 1);
}

sub import_file {
    my ($self, $file_path, $password) = @_;

    my $content = read_file($file_path);
    my $decoded = $self->_json->decode(lc $content);

    return $self->_from_object($decoded, $password);
}

sub _from_object {
    my ($self, $object, $password) = @_;

    my $version = $object->{version};

    croak 'Version not supported' unless $version && $version == 3;

    return $self->_from_v3($object, $password);

lib/Blockchain/Ethereum/RLP.pm  view on Meta::CPAN

=head1 SYNOPSIS

Allow RLP encoding and decoding

    my $rlp = Blockchain::Ethereum::RLP->new();

    my $tx_params  = ['0x9', '0x4a817c800', '0x5208', '0x3535353535353535353535353535353535353535', '0xde0b6b3a7640000', '0x', '0x1', '0x', '0x'];
    my $encoded = $rlp->encode($params); #ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080

    my $encoded_tx_params = 'ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080';
    my $decoded = $rlp->decode(pack "H*", $encoded_tx_params); #['0x9', '0x4a817c800', '0x5208', '0x3535353535353535353535353535353535353535', '0xde0b6b3a7640000', '0x', '0x1', '0x', '0x']

=head1 METHODS

=head2 encode

Encodes the given input to RLP

=over 4

=item * C<$input> hexadecimal string or reference to an hexadecimal string array

t/ABI/array.t  view on Meta::CPAN

    ];
    $encoder->function('foo')->append('address[]' => $addresses);
    my $encoded = $encoder->encode;

    my $encoded_expected =
        '0x13cb49d4000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...
    is $encoded, $encoded_expected;

    my $decoder = Blockchain::Ethereum::ABI::Decoder->new;

    my $decoded = $decoder->append('address[]')->decode(substr $encoded_expected, 10);
    is_deeply $decoded->[0], $addresses;
};

done_testing;

t/ABI/decode.t  view on Meta::CPAN

use strict;
use warnings;

use Test::More;
use Blockchain::Ethereum::ABI::Decoder;

my $decoder = Blockchain::Ethereum::ABI::Decoder->new();

subtest "Int" => sub {
    my $data    = "0x0000000000000000000000000000000000000000000000000858898f93629000";
    my $decoded = $decoder->append('uint256')->decode($data)->[0];
    is $decoded->bstr + 0, 601381800000000000;
};

subtest "String" => sub {
    my $data =
        "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000063496620796f75206472696e6b206d7563682066726f6d206120626f74746c65206d61726b65642027706f69736f6e2720697420697320636...
    my $decoded = $decoder->append('string')->decode($data)->[0];
    is $decoded, "If you drink much from a bottle marked 'poison' it is certain to disagree with you sooner or later.";
};

subtest "Bytes" => sub {
    my $data =
        "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000063496620796f75206472696e6b206d7563682066726f6d206120626f74746c65206d61726b65642027706f69736f6e2720697420697320636...

    my $decoded = $decoder->append('bytes')->decode($data)->[0];
    is $decoded,
        "0x496620796f75206472696e6b206d7563682066726f6d206120626f74746c65206d61726b65642027706f69736f6e27206974206973206365727461696e20746f206469736167726565207769746820796f7520736f6f6e6572206f72206c617465722e";
};

subtest "Address" => sub {
    my $data = "0x000000000000000000000000541662633a0097e3b429685505cd4d233dfe9167";

    my $decoded = $decoder->append('address')->decode($data)->[0];
    is $decoded, "0x541662633a0097e3b429685505cd4d233dfe9167";
};

subtest "Static Arrays" => sub {
    my $data = "0x61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000";
    my $decoded = $decoder->append('bytes3[2]')->decode($data);
    is_deeply $decoded->@*, ['0x' . unpack("H*", 'abc'), '0x' . unpack("H*", 'def')];
};

subtest "Dynamic Arrays" => sub {
    my $data =
        "0000000000000000000000000000000000000000000000000000000063538907000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000...
    my $decoded = $decoder->append('uint256')->append('bytes[]')->decode($data);
    is_deeply $decoded,
        [
        1666418951,
        [
            '0x04e45aaf000000000000000000000000def1ca1fb7fbcdc777520aa7f396b4e015f497ab000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000...
            '0x49404b7c00000000000000000000000000000000000000000000000000088face1a633580000000000000000000000009b4ac5feb3fa9c087906cce730dc1bed34f08514'
        ]];
};

subtest "Tuples" => sub {
    my $data =
        '0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000...

    my $decoded = $decoder->append(
        '(address,uint256,uint256,address,address,address,uint256,uint256,uint8,uint256,uint256,bytes32,uint256,bytes32,bytes32,uint256,(uint256,address)[],bytes)'
    )->decode($data)->[0];

    is_deeply $decoded,
        [
        '0x0000000000000000000000000000000000000000',
        Math::BigInt->new(0),
        Math::BigInt->new(2850000000000000),
        '0x5e9988b0c47b47a5b1d7d2e65358789044c2ef9a',
        '0x004c00500000ad104d7dbd00e3ae0a5c00560c00',
        '0x2cc8342d7c8bff5a213eb2cde39de9a59b3461a7',
        Math::BigInt->new(45981),
        Math::BigInt->new(1),
        Math::BigInt->new(2),

t/ABI/int.t  view on Meta::CPAN


subtest "Negative" => sub {
    my $encoder = Blockchain::Ethereum::ABI::Encoder->new;
    $encoder->function('foo')->append('int256' => -100);
    my $encoded = $encoder->encode;

    is $encoded, '0x4c970b2fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c';

    my $decoder = Blockchain::Ethereum::ABI::Decoder->new;

    my $decoded = $decoder->append('uint256')->decode('0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9c');
    is $decoded->[0], -100;
};

done_testing;

t/RLP/eip-155-example.t  view on Meta::CPAN

    # unsigned
    my $params  = ['0x9', '0x4a817c800', '0x5208', '0x3535353535353535353535353535353535353535', '0xde0b6b3a7640000', '0x', '0x1', '0x', '0x'];
    my $encoded = $rlp->encode($params);

    is(
        unpack("H*", $encoded),
        'ec098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a764000080018080',
        'encoding for unsigned transaction ok'
    );

    my $decoded = $rlp->decode($encoded);

    is_deeply($params, $decoded, 'decoding for unsigned transaction ok');

    #signed
    $params = [
        '0x9', '0x4a817c800', '0x5208', '0x3535353535353535353535353535353535353535',
        '0xde0b6b3a7640000', '0x', '0x25',
        '0x28ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276',
        '0x67cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83'
    ];

    $encoded = $rlp->encode($params);

    is(
        unpack("H*", $encoded),
        'f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83',
        'encoding for signed transaction ok'
    );

    $decoded = $rlp->decode($encoded);

    is_deeply($params, $decoded, 'decoding for signed transaction ok');
};

done_testing;

t/RLP/ethereum-org-example.t  view on Meta::CPAN

    my $rlp = Blockchain::Ethereum::RLP->new();

    my $dog   = unpack "H*", "dog";
    my $cat   = unpack "H*", "cat";
    my $lorem = unpack "H*", "Lorem ipsum dolor sit amet, consectetur adipisicing elit";

    my $encoded  = $rlp->encode($dog);
    my $expected = "83$dog";
    is(unpack("H*", $encoded), $expected, "correct encoding for dog");

    my $decoded = $rlp->decode($encoded);
    is_deeply $decoded, '0x' . $dog, "correct decoding for dog";

    my $cat_dog = [$cat, $dog];
    $encoded  = $rlp->encode($cat_dog);
    $expected = "c883@{[$cat]}83$dog";
    is(unpack("H*", $encoded), $expected, "correct encoding for cat dog");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, ['0x' . $cat, '0x' . $dog], "correct decoding for cat dog";

    $encoded  = $rlp->encode('');
    $expected = "80";
    is(unpack("H*", $encoded), $expected, "correct encoding for empty string");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, '0x', "correct decoding for empty string";

    $encoded  = $rlp->encode([]);
    $expected = "c0";
    is(unpack("H*", $encoded), $expected, "correct encoding for empty array reference");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, [], "correct decoding for empty array reference";

    $encoded  = $rlp->encode('0');
    $expected = '80';
    is(unpack("H*", $encoded), $expected, "correct encoding for empty = integer 0");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, '0x', "correct decoding for empty array empty = integer 0";

    $encoded = $rlp->encode('0x0');
    # 0 is set as null
    $expected = '80';
    is(unpack("H*", $encoded), $expected, "correct encoding for hexadecimal integer 0");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, '0x', "correct decoding for hexadecimal integer 0";

    $encoded  = $rlp->encode(sprintf("0x%x", 15));
    $expected = '0f';
    is(unpack("H*", $encoded), $expected, "correct encoding for hexadecimal integer 15");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, sprintf("0x%x", 15), "correct decoding for hexadecimal integer 15";

    $encoded  = $rlp->encode(sprintf("0x%x", 1024));
    $expected = '820400';
    is(unpack("H*", $encoded), $expected, "correct encoding for hexadecimal integer 1024");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, sprintf("0x%x", 1024), "correct decoding for hexadecimal integer 1024";

    $encoded  = $rlp->encode([[], [[]], [[], [[]]]]);
    $expected = "c7c0c1c0c3c0c1c0";
    is(unpack("H*", $encoded), $expected, "correct encoding for set theoretical representation of three");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, [[], [[]], [[], [[]]]], "correct decoding for set theoretical representation of three";

    $encoded  = $rlp->encode($lorem);
    $expected = "b838$lorem";
    is(unpack("H*", $encoded), $expected, "correct encoding for lorem");

    $decoded = $rlp->decode($encoded);
    is_deeply $decoded, '0x' . $lorem, "correct decoding for lorem";
};

done_testing;

t/RLP/etherscan_raw_txs.t  view on Meta::CPAN

use Blockchain::Ethereum::RLP;
my $rlp = Blockchain::Ethereum::RLP->new();

# https://etherscan.io/tx/0x784412e6b8ce1e6fcce97d149dea5367a594aef61d6d328398fffac0bb3ab537
subtest "etherscan raw tx => tether transfer" => sub {
    # 0x02 removed from raw tx since the transaction type is not part of the RLP encoding
    my $raw_tx =
        'f8b3018305c6c98405f5e100851d4adefbd882fde894dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb000000000000000000000000f8dd85f9dae9caee1c3560284715e8933add0de70000000000000000000000000000000000000000000000000000000004c50220c080a0b55239aaa...
    my $tether_transfer = $rlp->decode(pack "H*", $raw_tx);

    my $decoded = [
        '0x1',                                                                   # nonce
        '0x5c6c9',                                                               # chain id
        '0x5f5e100',                                                             # max priority fee per gas
        '0x1d4adefbd8',                                                          # max base fee per gas
        '0xfde8',                                                                # gas limit
        '0xdac17f958d2ee523a2206206994597c13d831ec7',                            # tether contract
        '0x',                                                                    # value
        '0xa9059cbb000000000000000000000000f8dd85f9dae9caee1c3560284715e8933add0de70000000000000000000000000000000000000000000000000000000004c50220'
        ,                                                                        # data
        [],                                                                      # access list
        '0x',                                                                    # v
        '0xb55239aaa8b77ddb8982509ab2bffa71f7b6a313017e4c71c560b7cb57a01c58',    # r
        '0x3f9d03d40ded1c2978a81a1c3c566b830a6a2f884ba238d4c095190793b28d7c'     # s
    ];

    is_deeply $tether_transfer, $decoded;

    is unpack("H*", $rlp->encode($tether_transfer)), $raw_tx;
};

# https://etherscan.io/tx/0x85fdf30e7ce3884b0b6ae4955416bb1dc48eedeef11ed5e4ef8e185fc21b0f4e
subtest "etherscan raw tx => eth transfer" => sub {
    my $raw_tx =
        'f8730181ae8405f5e100850aa1b5e50382520894004af85ea96fd3771ed2e1df6f2b152bc81b47c087ce911cd5adbf7680c080a0e045e7d62f53c4bb03c330a17ba909936f783da5d04af2587fc2d1c48d7e7a15a05554e82b338819fcb288fc28fb1f685b1e84eb5c897bb1c4a4b62a7877c313e2';

    my $eth_transfer = $rlp->decode(pack "H*", $raw_tx);

    my $decoded = [
        '0x1',    #
        '0xae',
        '0x5f5e100',
        '0xaa1b5e503',
        '0x5208',
        '0x04af85ea96fd3771ed2e1df6f2b152bc81b47c0',
        '0xce911cd5adbf76',
        '0x',
        [],
        '0x',
        '0xe045e7d62f53c4bb03c330a17ba909936f783da5d04af2587fc2d1c48d7e7a15',
        '0x5554e82b338819fcb288fc28fb1f685b1e84eb5c897bb1c4a4b62a7877c313e2'
    ];

    is_deeply $eth_transfer, $decoded;

    is unpack("H*", $rlp->encode($eth_transfer)), $raw_tx;

};

done_testing;

t/Transaction/eip1559.t  view on Meta::CPAN

    $key->sign_transaction($transaction);

    my $raw_transaction = $transaction->serialize;

    is(unpack("H*", $raw_transaction),
        '02f901c3820539808009831de2b98080b90170608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b604...
    );

    my $rlp = Blockchain::Ethereum::RLP->new();
    # substring to remove the 02
    my $decoded = $rlp->decode(substr($raw_transaction, 1));

    is hex $decoded->[-3], 0, 'correct eip155 v value for contract creation transaction';

};

subtest "eth transfer" => sub {
    my $transaction = Blockchain::Ethereum::Transaction::EIP1559->new(
        nonce                    => '0x1',
        max_fee_per_gas          => '0x9',
        max_priority_fee_per_gas => '0x0',
        gas_limit                => '0x5208',
        to                       => '0x3535353535353535353535353535353535353535',

t/Transaction/eip1559.t  view on Meta::CPAN

    $key->sign_transaction($transaction);

    my $raw_transaction = $transaction->serialize;

    is(unpack("H*", $raw_transaction),
        '02f86c820539018009825208943535353535353535353535353535353535353535880de0b6b3a764000080c080a070816c3d026c13a53e98e5dc414398e9dcdf23e440e777114a3e04810e0dfb5da07d732e6b7f847b06d2baed033772d78407da8f4010fa9300df79f2209ba4c7a0'
    );

    my $rlp = Blockchain::Ethereum::RLP->new();
    # substring to remove the 02
    my $decoded = $rlp->decode(substr($raw_transaction, 1));

    is hex $decoded->[-3], 0, 'correct eip155 v value for contract creation transaction';

};

done_testing;

t/Transaction/legacy.t  view on Meta::CPAN


    $key->sign_transaction($transaction);

    my $raw_transaction = $transaction->serialize;

    is(unpack("H*", $raw_transaction),
        'f86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83'
    );

    my $rlp     = Blockchain::Ethereum::RLP->new();
    my $decoded = $rlp->decode($raw_transaction);

    is hex $decoded->[-3], 37, 'correct eip155 v value';
};

done_testing;



( run in 2.351 seconds using v1.01-cache-2.11-cpan-211d0254c34 )