diff --git a/modules/sdk-coin-avaxp/src/lib/permissionlessValidatorTxBuilder.ts b/modules/sdk-coin-avaxp/src/lib/permissionlessValidatorTxBuilder.ts index 7cbd32ef01..df995c344b 100644 --- a/modules/sdk-coin-avaxp/src/lib/permissionlessValidatorTxBuilder.ts +++ b/modules/sdk-coin-avaxp/src/lib/permissionlessValidatorTxBuilder.ts @@ -475,11 +475,12 @@ export class PermissionlessValidatorTxBuilder extends TransactionBuilder { ); stakeOutputs.push(stakeOutput); - if (currentTotal >= totalTarget) { + const changeOutputAmount = currentTotal - totalTarget; + if (currentTotal >= totalTarget && changeOutputAmount > 0) { const changeOutput = new avaxSerial.TransferableOutput( assetId, new TransferOutput( - new BigIntPr(currentTotal - totalTarget), + new BigIntPr(changeOutputAmount), new OutputOwners( new BigIntPr(this.transaction._locktime), new Int(this.transaction._threshold), diff --git a/modules/sdk-coin-avaxp/test/resources/avaxp.ts b/modules/sdk-coin-avaxp/test/resources/avaxp.ts index f6cdadb09b..874b35e573 100644 --- a/modules/sdk-coin-avaxp/test/resources/avaxp.ts +++ b/modules/sdk-coin-avaxp/test/resources/avaxp.ts @@ -614,6 +614,7 @@ export const BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE = { startTime: '1656423398', endTime: '1659053398', stakeAmount: '2370000000', + stakeAmountNoOutput: '4097000000', delegationFeeRate: 10, nodeId: 'NodeID-2hMqBQdjZMWdHvYu7ZPLA2CmrAdbTvpGf', blsPublicKey: '0xad9e9476b701edec88e53b1c314456053b3cf846a1192117872e41455f440c074d6ee89530d45e88f79ac0eda06f2887', diff --git a/modules/sdk-coin-avaxp/test/unit/lib/permissionlessValidatorTxBuilder.ts b/modules/sdk-coin-avaxp/test/unit/lib/permissionlessValidatorTxBuilder.ts index b150024ded..5f49077ea0 100644 --- a/modules/sdk-coin-avaxp/test/unit/lib/permissionlessValidatorTxBuilder.ts +++ b/modules/sdk-coin-avaxp/test/unit/lib/permissionlessValidatorTxBuilder.ts @@ -298,4 +298,30 @@ describe('AvaxP permissionlessValidatorTxBuilder', () => { console.log(fullSignedTx.toJson()); }); }); + it('Should fail to build if utxos change output 0', async () => { + const unixNow = BigInt(Math.round(new Date().getTime() / 1000)); + const startTime = unixNow + BigInt(60); + const endTime = startTime + BigInt(60 * 60 * 24 + 600); + + const txBuilder = new AvaxpLib.TransactionBuilderFactory(coins.get('tavaxp')) + .getPermissionlessValidatorTxBuilder() + .threshold(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.threshold) + .locktime(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.locktime) + .recoverMode(false) + .fromPubKey(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.bitgoAddresses) + .startTime(startTime.toString()) + .endTime(endTime.toString()) + .stakeAmount(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.stakeAmountNoOutput) + .delegationFeeRate(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.delegationFeeRate) + .nodeID(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.nodeId) + .blsPublicKey(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.blsPublicKey) + .blsSignature(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.blsSignature) + .utxos(testData.BUILD_AND_SIGN_ADD_PERMISSIONLESS_VALIDATOR_SAMPLE.utxos); + const tx = await txBuilder.build(); + const txJson = tx.toJson(); + const txExplain = tx.explainTransaction(); + txJson.changeOutputs.length.should.equal(0); + txExplain.changeOutputs.length.should.equal(0); + txExplain.changeAmount.should.equal('0'); + }); });