Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(abstract-eth): fix issue related to chain id #4177

Merged
merged 1 commit into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion modules/sdk-coin-arbeth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"@bitgo/statics": "^39.0.0",
"@bitgo/utxo-lib": "^9.26.0",
"@ethereumjs/common": "^2.6.5",
"superagent": "^3.8.3"
"superagent": "^3.8.3",
"ethereumjs-abi": "^0.6.5",
"ethereumjs-util": "7.1.5"
},
"devDependencies": {
"@bitgo/sdk-api": "^1.34.0",
Expand Down
9 changes: 9 additions & 0 deletions modules/sdk-coin-arbeth/test/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@ export const SEND_TOKEN_AMOUNT_ZERO_DATA =

export const SEND_FUNDS_NO_KEY_DATA =
'0x391252150000000000000000000000007325a3f7d4f9e86ae62cf742426078c3755730d5000000000000000000000000000000000000000000000000016345785d8a000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec6ab34000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000';

export const SEND_TX_BROADCAST_LEGACY =
'0xf901cd02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410374eff4ca3b3d8c7b37ac7515ea4d212847bdc08a5ede459436c3ebcfd7f9b855d021e7590b6fa36d68ba1c58fc568d52d6794e465f6687da90cc70aa3335231b00000000000000000000000000000000000000000000000000000000000000830cde00a074b64b8ffaf205436aa4bfcbb78e98329f4fed4f11bf3b40f9eef5a9a16bc165a01740883cc0236ab97286398d114d8bebc1a0717558d45533bebb7e5c130eeff6';

export const SEND_TOKEN_TX_BROADCAST =
'0xf901ad02843b9aca0083b8a1a094df7decb1baa8f529f0c8982cbb4be5035719529980b901440dcd7a6c00000000000000000000000072c2c8e08bf91d755cd7d26b49a2ee3dc99de1b90000000000000000000000000000000000000000000000000000000000000064000000000000000000000000143e1dae4f018ff86051a01d44a1b49b13704056000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000041bec4f4b3c7f2b3701694d615794a5fa9ee2e097e50d2873e6b17b565b44900920b6e2fbc97cdc7fc690a71a509ad08851bd69c99e999660a892ccf67b9c2c8a31c00000000000000000000000000000000000000000000000000000000000000830cddffa0c12178bc3bd603a415f7510a9160a774828176b86105913685309f3e64bbd00fa01d8593a7d051656bb0023219f98f6da708fade85f26e7c974a8eaa0246c2e795';

export const SEND_TX_AMOUNT_ZERO_BROADCAST =
'0xf901cd02843b9aca0083b8a1a0948f977e912ef500548a0c3be6ddde9899f1199b8180b901643912521500000000000000000000000019645032c7f1533395d44a629462e751084d3e4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000005ec67e28000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000415bba6d3d5288d585cbb01997410bce555295a19ab7ede922866ae0c9b50698754f494bd624ea91a4b098e9d17080cc3af571cedad6334c4be1e6e49498af68481c00000000000000000000000000000000000000000000000000000000000000830cde00a0e0421465dee286fd38937b8ea67807fc30265ac5fb5e7ea23ae73074ef22a1b8a032ed7887c90ade813e659e63145409d7ac896342eb02674524184e806004945f';
158 changes: 158 additions & 0 deletions modules/sdk-coin-arbeth/test/unit/transactionBuilder/send.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import { TransactionType, BaseTransaction } from '@bitgo/sdk-core';
import { coins } from '@bitgo/statics';
import EthereumAbi from 'ethereumjs-abi';
import should from 'should';
import * as ethUtil from 'ethereumjs-util';

import { decodeTransferData, KeyPair } from '@bitgo/abstract-eth';
import * as testData from '../../resources';
import { getBuilder } from '../../getBuilder';
import { TransactionBuilder } from '../../../src';

describe('Arbeth transaction builder send', () => {
describe('should sign and build', () => {
let txBuilder;
let key;
let contractAddress;

const getOperationHash = function (tx: BaseTransaction): string {
const { data } = tx.toJson();
const { tokenContractAddress, expireTime, sequenceId, amount, to } = decodeTransferData(data);
const operationParams = [
['string', 'address', 'uint', 'address', 'uint', 'uint'],
[
'421614-ERC20',
new ethUtil.BN(ethUtil.stripHexPrefix(to), 16),
amount,
new ethUtil.BN(ethUtil.stripHexPrefix(tokenContractAddress || ''), 16),
expireTime,
sequenceId,
],
];
return EthereumAbi.soliditySHA3(...operationParams);
};

beforeEach(() => {
contractAddress = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
txBuilder = getBuilder('tarbeth') as TransactionBuilder;
key = testData.KEYPAIR_PRV.getKeys().prv as string;
txBuilder.fee({
fee: '1000000000',
gasLimit: '12100000',
});
txBuilder.counter(2);
txBuilder.type(TransactionType.Send);
txBuilder.contract(contractAddress);
});

it('a send funds transaction', async () => {
const recipient = '0x19645032c7f1533395d44a629462e751084d3e4c';
const amount = '1000000000';
const expireTime = 1590066728;
const sequenceId = 5;
txBuilder
.transfer()
.coin('tarbeth')
.amount(amount)
.to(recipient)
.expirationTime(expireTime)
.contractSequenceId(sequenceId)
.key(key);
txBuilder.sign({ key: testData.PRIVATE_KEY_1 });
const tx = await txBuilder.build();

should.equal(tx.toJson().chainId, 421614);
should.equal(tx.toBroadcastFormat(), testData.SEND_TX_BROADCAST_LEGACY);
should.equal(tx.signature.length, 2);
should.equal(tx.inputs.length, 1);
should.equal(tx.inputs[0].address, contractAddress);
should.equal(tx.inputs[0].value, amount);

should.equal(tx.outputs.length, 1);
should.equal(tx.outputs[0].address, recipient);
should.equal(tx.outputs[0].value, amount);

const data = tx.toJson().data;
const {
to,
amount: parsedAmount,
expireTime: parsedExpireTime,
sequenceId: parsedSequenceId,
} = decodeTransferData(data);
should.equal(to, recipient);
should.equal(parsedAmount, amount);
should.equal(parsedExpireTime, expireTime);
should.equal(parsedSequenceId, sequenceId);
});

it('a send funds with amount 0 transaction', async () => {
txBuilder
.transfer()
.coin('tarbeth')
.amount('0')
.to('0x19645032c7f1533395d44a629462e751084d3e4c')
.expirationTime(1590066728)
.contractSequenceId(5)
.key(key);
txBuilder.sign({ key: testData.PRIVATE_KEY_1 });
const tx = await txBuilder.build();
should.equal(tx.toBroadcastFormat(), testData.SEND_TX_AMOUNT_ZERO_BROADCAST);
});

it('a send token transaction', async () => {
const recipient = '0x72c2c8e08bf91d755cd7d26b49a2ee3dc99de1b9';
const contractAddress = '0xdf7decb1baa8f529f0c8982cbb4be50357195299';
const amount = '100';
txBuilder.contract(contractAddress);
txBuilder
.transfer()
.coin('tarbeth:link')
.amount(amount)
.to(recipient)
.expirationTime(1590066728)
.contractSequenceId(5)
.key(key);
txBuilder.sign({
key: testData.PRIVATE_KEY_1,
});
const tx = await txBuilder.build();

should.equal(tx.toBroadcastFormat(), testData.SEND_TOKEN_TX_BROADCAST);
should.equal(tx.signature.length, 2);
should.equal(tx.inputs.length, 1);
should.equal(tx.inputs[0].address, contractAddress);
should.equal(tx.inputs[0].value, amount);
should.equal(tx.inputs[0].coin, 'tarbeth:link');

should.equal(tx.outputs.length, 1);
should.equal(tx.outputs[0].address, recipient);
should.equal(tx.outputs[0].value, amount);
should.equal(tx.outputs[0].coin, 'tarbeth:link');

const { signature } = decodeTransferData(tx.toJson().data);
const operationHash = getOperationHash(tx);

const { v, r, s } = ethUtil.fromRpcSig(signature);
const senderPubKey = ethUtil.ecrecover(Buffer.from(operationHash, 'hex'), v, r, s);
const senderAddress = ethUtil.pubToAddress(senderPubKey);
const senderKey = new KeyPair({ prv: testData.PRIVATE_KEY_1 });
ethUtil.bufferToHex(senderAddress).should.equal(senderKey.getAddress());
});

it('a send token transactions from serialized', async () => {
const txBuilder = new TransactionBuilder(coins.get('tarbeth'));
txBuilder.from(testData.SEND_TOKEN_TX_BROADCAST);
const tx = await txBuilder.build();
should.equal(tx.toBroadcastFormat(), testData.SEND_TOKEN_TX_BROADCAST);

const { signature } = decodeTransferData(tx.toJson().data);
const operationHash = getOperationHash(tx);

const { v, r, s } = ethUtil.fromRpcSig(signature);
const senderPubKey = ethUtil.ecrecover(Buffer.from(operationHash || ''), v, r, s);
const senderAddress = ethUtil.pubToAddress(senderPubKey);
const senderKey = new KeyPair({ prv: testData.PRIVATE_KEY_1 });
ethUtil.bufferToHex(senderAddress).should.equal(senderKey.getAddress());
});
});
});
3 changes: 1 addition & 2 deletions modules/sdk-coin-arbeth/test/unit/transferBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import should from 'should';
import { KeyPair, TransferBuilder } from '../../src';

import * as testData from '../resources';

describe('Eth send multi sig builder', function () {
describe('Arbeth send multi sig builder', function () {
const toAddress = '0x7325A3F7d4f9E86AE62Cf742426078C3755730d5';
const xprv =
'xprv9s21ZrQH143K3D8TXfvAJgHVfTEeQNW5Ys9wZtnUZkqPzFzSjbEJrWC1vZ4GnXCvR7rQL2UFX3RSuYeU9MrERm1XBvACow7c36vnz5iYyj2';
Expand Down
4 changes: 3 additions & 1 deletion modules/sdk-coin-opeth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@
"@bitgo/statics": "^39.0.0",
"@bitgo/utxo-lib": "^9.26.0",
"@ethereumjs/common": "^2.6.5",
"superagent": "^3.8.3"
"superagent": "^3.8.3",
"ethereumjs-abi": "^0.6.5",
"ethereumjs-util": "7.1.5"
},
"devDependencies": {
"@bitgo/sdk-api": "^1.34.0",
Expand Down
23 changes: 22 additions & 1 deletion modules/sdk-coin-opeth/src/lib/transferBuilder.ts
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
export { TransferBuilder } from '@bitgo/abstract-eth';
import { TransferBuilder as EthTransferBuilder } from '@bitgo/abstract-eth';

/** OPETH transfer builder */
export class TransferBuilder extends EthTransferBuilder {
/**
* Get the prefix used in generating an operation hash for sending tokens
*
* @returns the string prefix
*/
protected getTokenOperationHashPrefix(): string {
return 'OPETH-ERC20';
}

/**
* Get the prefix used in generating an operation hash for sending native coins
*
* @returns the string prefix
*/
protected getNativeOperationHashPrefix(): string {
return 'OPETH';
}
}
Loading
Loading