@@ -9,21 +9,6 @@ describe('VET Staking Transaction', function () {
99 const factory = new TransactionBuilderFactory ( coins . get ( 'tvet' ) ) ;
1010 const stakingContractAddress = '0x1EC1D168574603ec35b9d229843B7C2b44bCB770' ;
1111 const amountToStake = '1000000000000000000' ; // 1 VET in wei
12- const stakingContractABI = [
13- {
14- inputs : [
15- {
16- internalType : 'uint256' ,
17- name : 'amount' ,
18- type : 'uint256' ,
19- } ,
20- ] ,
21- name : 'stake' ,
22- outputs : [ ] ,
23- stateMutability : 'payable' ,
24- type : 'function' ,
25- } ,
26- ] ;
2712
2813 // Helper function to create a basic transaction builder with common properties
2914 const createBasicTxBuilder = ( ) => {
@@ -42,7 +27,7 @@ describe('VET Staking Transaction', function () {
4227 const txBuilder = factory . getStakingBuilder ( ) ;
4328 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
4429 txBuilder . amountToStake ( amountToStake ) ;
45- txBuilder . stakingContractABI ( stakingContractABI ) ;
30+ txBuilder . stakingContractABI ( EthereumAbi ) ;
4631 txBuilder . sender ( '0x9378c12BD7502A11F770a5C1F223c959B2805dA9' ) ;
4732 txBuilder . chainTag ( 0x27 ) ; // Testnet chain tag
4833 txBuilder . blockRef ( '0x0000000000000000' ) ;
@@ -59,7 +44,7 @@ describe('VET Staking Transaction', function () {
5944 const stakingTx = tx as StakingTransaction ;
6045 stakingTx . stakingContractAddress . should . equal ( stakingContractAddress ) ;
6146 stakingTx . amountToStake . should . equal ( amountToStake ) ;
62- stakingTx . stakingContractABI . should . deepEqual ( stakingContractABI ) ;
47+ stakingTx . stakingContractABI . should . deepEqual ( EthereumAbi ) ;
6348
6449 // Verify clauses
6550 stakingTx . clauses . length . should . equal ( 1 ) ;
@@ -93,15 +78,15 @@ describe('VET Staking Transaction', function () {
9378 it ( 'should throw error when stakingContractAddress is missing' , async function ( ) {
9479 const txBuilder = createBasicTxBuilder ( ) ;
9580 txBuilder . amountToStake ( amountToStake ) ;
96- txBuilder . stakingContractABI ( stakingContractABI ) ;
81+ txBuilder . stakingContractABI ( EthereumAbi ) ;
9782
9883 await txBuilder . build ( ) . should . be . rejectedWith ( 'Staking contract address is required' ) ;
9984 } ) ;
10085
10186 it ( 'should throw error when amountToStake is missing' , async function ( ) {
10287 const txBuilder = createBasicTxBuilder ( ) ;
10388 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
104- txBuilder . stakingContractABI ( stakingContractABI ) ;
89+ txBuilder . stakingContractABI ( EthereumAbi ) ;
10590
10691 await txBuilder . build ( ) . should . be . rejectedWith ( 'Amount to stake is required' ) ;
10792 } ) ;
@@ -115,10 +100,44 @@ describe('VET Staking Transaction', function () {
115100 } ) . throw ( / I n v a l i d a d d r e s s / ) ;
116101 } ) ;
117102
103+ it ( 'should throw error when amountToStake is not a valid number string' , async function ( ) {
104+ const txBuilder = createBasicTxBuilder ( ) ;
105+ txBuilder . stakingContractAddress ( stakingContractAddress ) ;
106+ txBuilder . stakingContractABI ( EthereumAbi ) ;
107+
108+ // Invalid amount (not a number)
109+ should ( ( ) => {
110+ txBuilder . amountToStake ( 'not-a-number' ) ;
111+ } ) . not . throw ( ) ; // The setter doesn't validate
112+ // But it should fail when building the transaction
113+ await txBuilder . build ( ) . should . be . rejectedWith ( / I n v a l i d c h a r a c t e r / ) ;
114+ } ) ;
115+
116+ it ( 'should pass validation with any ABI object but may fail during build' , async function ( ) {
117+ const txBuilder = createBasicTxBuilder ( ) ;
118+ txBuilder . stakingContractAddress ( stakingContractAddress ) ;
119+ txBuilder . amountToStake ( amountToStake ) ;
120+
121+ // Set an invalid ABI object
122+ const invalidAbi = { } ;
123+ txBuilder . stakingContractABI ( invalidAbi as EthereumAbi ) ;
124+
125+ // The validation will pass because it only checks if the ABI property exists
126+ // But the build might fail if the ABI is actually used in the build process
127+ // Since the actual encoding is done by utils.getStakingData() which doesn't use
128+ // the ABI set on the transaction, this might still succeed
129+ try {
130+ await txBuilder . build ( ) ;
131+ } catch ( e ) {
132+ // If it fails, it should be because of an invalid ABI
133+ e . message . should . match ( / m e t h o d I D | r a w E n c o d e / ) ;
134+ }
135+ } ) ;
136+
118137 it ( 'should allow zero amountToStake but encode it properly' , async function ( ) {
119138 const txBuilder = createBasicTxBuilder ( ) ;
120139 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
121- txBuilder . stakingContractABI ( stakingContractABI ) ;
140+ txBuilder . stakingContractABI ( EthereumAbi ) ;
122141 txBuilder . amountToStake ( '0' ) ;
123142
124143 const tx = await txBuilder . build ( ) ;
@@ -133,28 +152,21 @@ describe('VET Staking Transaction', function () {
133152 stakingTx . clauses [ 0 ] . data . should . equal ( expectedData ) ;
134153 } ) ;
135154
136- it ( 'should generate correct transaction data even without explicitly setting stakingContractABI ' , async function ( ) {
155+ it ( 'should throw error when stakingContractABI is missing ' , async function ( ) {
137156 const txBuilder = createBasicTxBuilder ( ) ;
138157 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
139158 txBuilder . amountToStake ( amountToStake ) ;
140159 // Not setting stakingContractABI
141160
142- const tx = await txBuilder . build ( ) ;
143- tx . should . be . instanceof ( StakingTransaction ) ;
144-
145- const stakingTx = tx as StakingTransaction ;
146- // Verify the transaction data is correctly generated using the default staking method ID
147- stakingTx . clauses [ 0 ] . data . should . startWith ( STAKING_METHOD_ID ) ;
148- // Verify the encoded amount matches what we expect
149- const expectedData = '0xa694fc3a0000000000000000000000000000000000000000000000000de0b6b3a7640000' ;
150- stakingTx . clauses [ 0 ] . data . should . equal ( expectedData ) ;
161+ // Should fail when trying to build without ABI
162+ await txBuilder . build ( ) . should . be . rejectedWith ( 'Staking contract ABI is required' ) ;
151163 } ) ;
152164
153165 it ( 'should build transaction with undefined sender but include it in inputs' , async function ( ) {
154166 const txBuilder = factory . getStakingBuilder ( ) ;
155167 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
156168 txBuilder . amountToStake ( amountToStake ) ;
157- txBuilder . stakingContractABI ( stakingContractABI ) ;
169+ txBuilder . stakingContractABI ( EthereumAbi ) ;
158170 txBuilder . chainTag ( 0x27 ) ;
159171 txBuilder . blockRef ( '0x0000000000000000' ) ;
160172 txBuilder . expiration ( 64 ) ;
@@ -181,7 +193,7 @@ describe('VET Staking Transaction', function () {
181193 const txBuilder = factory . getStakingBuilder ( ) ;
182194 txBuilder . stakingContractAddress ( stakingContractAddress ) ;
183195 txBuilder . amountToStake ( amountToStake ) ;
184- txBuilder . stakingContractABI ( stakingContractABI ) ;
196+ txBuilder . stakingContractABI ( EthereumAbi ) ;
185197 // Not setting chainTag
186198 txBuilder . blockRef ( '0x0000000000000000' ) ;
187199 txBuilder . expiration ( 64 ) ;
@@ -197,5 +209,53 @@ describe('VET Staking Transaction', function () {
197209 // Verify the chainTag is set to the testnet default (39)
198210 stakingTx . chainTag . should . equal ( 39 ) ;
199211 } ) ;
212+
213+ it ( 'should verify ABI encoding matches expected output for different amounts' , async function ( ) {
214+ const txBuilder = createBasicTxBuilder ( ) ;
215+ txBuilder . stakingContractAddress ( stakingContractAddress ) ;
216+ txBuilder . stakingContractABI ( EthereumAbi ) ;
217+
218+ // Test with a different amount
219+ const differentAmount = '500000000000000000' ; // 0.5 VET
220+ txBuilder . amountToStake ( differentAmount ) ;
221+
222+ const tx = await txBuilder . build ( ) ;
223+ const stakingTx = tx as StakingTransaction ;
224+
225+ // Manually encode the expected data
226+ const methodName = 'stake' ;
227+ const types = [ 'uint256' ] ;
228+ const params = [ new BN ( differentAmount ) ] ;
229+
230+ const method = EthereumAbi . methodID ( methodName , types ) ;
231+ const args = EthereumAbi . rawEncode ( types , params ) ;
232+ const expectedData = '0x' + Buffer . concat ( [ method , args ] ) . toString ( 'hex' ) ;
233+
234+ // Verify the transaction data matches our manual encoding
235+ stakingTx . clauses [ 0 ] . data . should . equal ( expectedData ) ;
236+ stakingTx . clauses [ 0 ] . data . should . startWith ( STAKING_METHOD_ID ) ;
237+ } ) ;
238+
239+ it ( 'should handle extremely large stake amounts correctly' , async function ( ) {
240+ const txBuilder = createBasicTxBuilder ( ) ;
241+ txBuilder . stakingContractAddress ( stakingContractAddress ) ;
242+ txBuilder . stakingContractABI ( EthereumAbi ) ;
243+
244+ // Test with a very large amount (near uint256 max)
245+ const largeAmount = '115792089237316195423570985008687907853269984665640564039457584007913129639935' ; // 2^256 - 1
246+ txBuilder . amountToStake ( largeAmount ) ;
247+
248+ const tx = await txBuilder . build ( ) ;
249+ const stakingTx = tx as StakingTransaction ;
250+
251+ // Verify the amount is stored correctly
252+ stakingTx . amountToStake . should . equal ( largeAmount ) ;
253+
254+ // The data should still be properly encoded
255+ stakingTx . clauses [ 0 ] . data . should . startWith ( STAKING_METHOD_ID ) ;
256+
257+ // Verify recipients
258+ stakingTx . recipients [ 0 ] . amount . should . equal ( largeAmount ) ;
259+ } ) ;
200260 } ) ;
201261} ) ;
0 commit comments