Skip to content

Commit 24ddf60

Browse files
fix(sdk-coin-vet): add stake amount in the validator registration txn
Ticket: SC-4409
1 parent c57dd55 commit 24ddf60

File tree

3 files changed

+75
-6
lines changed

3 files changed

+75
-6
lines changed

modules/sdk-coin-vet/src/lib/transaction/validatorRegistrationTransaction.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import EthereumAbi from 'ethereumjs-abi';
77
import utils from '../utils';
88
import BigNumber from 'bignumber.js';
99
import { addHexPrefix, BN } from 'ethereumjs-util';
10-
import { ZERO_VALUE_AMOUNT } from '../constants';
1110

1211
export class ValidatorRegistrationTransaction extends Transaction {
1312
private _stakingContractAddress: string;
1413
private _validator: string;
1514
private _stakingPeriod: number;
15+
private _amountToStake: string;
1616

1717
constructor(_coinConfig: Readonly<CoinConfig>) {
1818
super(_coinConfig);
@@ -35,6 +35,14 @@ export class ValidatorRegistrationTransaction extends Transaction {
3535
this._stakingPeriod = period;
3636
}
3737

38+
get amountToStake(): string {
39+
return this._amountToStake;
40+
}
41+
42+
set amountToStake(amount: string) {
43+
this._amountToStake = amount;
44+
}
45+
3846
get stakingContractAddress(): string {
3947
return this._stakingContractAddress;
4048
}
@@ -63,7 +71,7 @@ export class ValidatorRegistrationTransaction extends Transaction {
6371
this._clauses = [
6472
{
6573
to: this.stakingContractAddress,
66-
value: ZERO_VALUE_AMOUNT,
74+
value: this.amountToStake,
6775
data: addValidationData,
6876
},
6977
];
@@ -72,7 +80,7 @@ export class ValidatorRegistrationTransaction extends Transaction {
7280
this._recipients = [
7381
{
7482
address: this.stakingContractAddress,
75-
amount: ZERO_VALUE_AMOUNT,
83+
amount: this.amountToStake,
7684
},
7785
];
7886
}
@@ -107,11 +115,11 @@ locking their VET into the built-in staker contract. Allowed values are 60480 (7
107115
dependsOn: this.dependsOn,
108116
nonce: this.nonce,
109117
data: this.transactionData,
110-
value: ZERO_VALUE_AMOUNT,
118+
value: this.amountToStake,
111119
sender: this.sender,
112120
to: this.stakingContractAddress,
113121
stakingContractAddress: this.stakingContractAddress,
114-
amountToStake: ZERO_VALUE_AMOUNT,
122+
amountToStake: this.amountToStake,
115123
validatorAddress: this.validator,
116124
stakingPeriod: this.stakingPeriod,
117125
};

modules/sdk-coin-vet/src/lib/transactionBuilder/validatorRegistrationBuilder.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import assert from 'assert';
22
import { BaseCoin as CoinConfig } from '@bitgo/statics';
33
import { TransactionType } from '@bitgo/sdk-core';
44
import { TransactionClause } from '@vechain/sdk-core';
5+
import BigNumber from 'bignumber.js';
56

67
import { TransactionBuilder } from './transactionBuilder';
78
import { Transaction } from '../transaction/transaction';
@@ -96,6 +97,25 @@ export class ValidatorRegistrationBuilder extends TransactionBuilder {
9697
return this;
9798
}
9899

100+
/**
101+
* Sets the amount to stake for this validator registration tx (VET amount being sent).
102+
*
103+
* @param {string} amount - The amount to stake in wei
104+
* @returns {ValidatorRegistrationBuilder} This transaction builder
105+
*/
106+
amountToStake(amount: string): this {
107+
// Convert amount from wei to VET for validation (1 VET = 10^18 wei)
108+
const amountInVET = new BigNumber(amount).dividedBy(new BigNumber(10).pow(18));
109+
110+
// Validate amount is between 25M and 600M VET
111+
if (amountInVET.isLessThan(25_000_000) || amountInVET.isGreaterThan(600_000_000)) {
112+
throw new Error('Staking amount must be between 25M and 600M VET');
113+
}
114+
115+
this.validatorRegistrationTransaction.amountToStake = amount;
116+
return this;
117+
}
118+
99119
/**
100120
* Sets the validator address for this validator registration tx.
101121
* @param {string} address - The validator address
@@ -127,9 +147,16 @@ export class ValidatorRegistrationBuilder extends TransactionBuilder {
127147
throw new Error('transaction not defined');
128148
}
129149
assert(transaction.stakingContractAddress, 'Staking contract address is required');
130-
131150
assert(transaction.stakingPeriod, 'Staking period is required');
132151
assert(transaction.validator, 'Validator address is required');
152+
assert(transaction.amountToStake, 'Staking amount is required');
153+
154+
// Validate staking amount is within allowed range
155+
const amountInVET = new BigNumber(transaction.amountToStake).dividedBy(new BigNumber(10).pow(18));
156+
if (amountInVET.isLessThan(25_000_000) || amountInVET.isGreaterThan(600_000_000)) {
157+
throw new Error('Staking amount must be between 25M and 600M VET');
158+
}
159+
133160
this.validateAddress({ address: transaction.stakingContractAddress });
134161
}
135162

modules/sdk-coin-vet/test/transactionBuilder/validatorRegistrationTxnBuilder.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ describe('VET Validator Registration Transaction', function () {
1414
const factory = new TransactionBuilderFactory(coins.get('tvet'));
1515
const stakingPeriod = 60480;
1616
const validatorAddress = '0x9a7aFCACc88c106f3bbD6B213CD0821D9224d945';
17+
const amountToStake = '25000000000000000000000000'; // 25000000 VET
18+
const amountLessThanMinStake = '24000000000000000000000000'; // 24000000 VET
19+
const amountGreaterThanMaxStake = '650000000000000000000000000'; // 650000000 VET
1720

1821
// Helper function to create a basic transaction builder with common properties
1922
const createBasicTxBuilder = () => {
@@ -32,6 +35,7 @@ describe('VET Validator Registration Transaction', function () {
3235
const txBuilder = factory.getValidatorRegistrationBuilder();
3336
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
3437
txBuilder.stakingPeriod(stakingPeriod);
38+
txBuilder.amountToStake(amountToStake);
3539
txBuilder.sender('0x9378c12BD7502A11F770a5C1F223c959B2805dA9');
3640
txBuilder.chainTag(0x27); // Testnet chain tag
3741
txBuilder.blockRef('0x0000000000000000');
@@ -88,6 +92,7 @@ describe('VET Validator Registration Transaction', function () {
8892
const txBuilder = createBasicTxBuilder();
8993
txBuilder.stakingPeriod(stakingPeriod);
9094
txBuilder.validator(validatorAddress);
95+
txBuilder.amountToStake(amountToStake);
9196

9297
await txBuilder.build().should.be.rejectedWith('Staking contract address is required');
9398
});
@@ -96,6 +101,7 @@ describe('VET Validator Registration Transaction', function () {
96101
const txBuilder = createBasicTxBuilder();
97102
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
98103
txBuilder.validator(validatorAddress);
104+
txBuilder.amountToStake(amountToStake);
99105

100106
await txBuilder.build().should.be.rejectedWith('Staking period is required');
101107
});
@@ -104,6 +110,34 @@ describe('VET Validator Registration Transaction', function () {
104110
const txBuilder = createBasicTxBuilder();
105111
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
106112
txBuilder.stakingPeriod(stakingPeriod);
113+
txBuilder.amountToStake(amountToStake);
114+
115+
await txBuilder.build().should.be.rejectedWith('Validator address is required');
116+
});
117+
118+
it('should throw error when amount is missing', async function () {
119+
const txBuilder = createBasicTxBuilder();
120+
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
121+
txBuilder.stakingPeriod(stakingPeriod);
122+
txBuilder.validator(validatorAddress);
123+
124+
await txBuilder.build().should.be.rejectedWith('Validator address is required');
125+
});
126+
127+
it('should throw error when amount is less than minimum', async function () {
128+
const txBuilder = createBasicTxBuilder();
129+
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
130+
txBuilder.stakingPeriod(stakingPeriod);
131+
txBuilder.amountToStake(amountLessThanMinStake);
132+
133+
await txBuilder.build().should.be.rejectedWith('Validator address is required');
134+
});
135+
136+
it('should throw error when amount is greater than maximum', async function () {
137+
const txBuilder = createBasicTxBuilder();
138+
txBuilder.stakingContractAddress(VALIDATOR_REGISTRATION_STAKER_CONTRACT_ADDRESS_TESTNET);
139+
txBuilder.stakingPeriod(stakingPeriod);
140+
txBuilder.amountToStake(amountGreaterThanMaxStake);
107141

108142
await txBuilder.build().should.be.rejectedWith('Validator address is required');
109143
});

0 commit comments

Comments
 (0)