Skip to content

Commit

Permalink
Merge pull request #4177 from BitGo/WIN-1446-update-chainid-related-c…
Browse files Browse the repository at this point in the history
…hanges

fix(abstract-eth): fix issue related to chain id
  • Loading branch information
gianchandania authored Jan 4, 2024
2 parents acba8a4 + c3a21c4 commit a006d5a
Show file tree
Hide file tree
Showing 13 changed files with 508 additions and 22 deletions.
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

0 comments on commit a006d5a

Please sign in to comment.