-
Notifications
You must be signed in to change notification settings - Fork 164
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add validateAvaxBurnedAmountEtna
- Loading branch information
1 parent
5b7868a
commit b685484
Showing
10 changed files
with
706 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export const upgradesInfo = { | ||
apricotPhaselTime: '2020-12-05T05:00:00Z', | ||
apricotPhase2Time: '2020-12-05T05:00:00Z', | ||
apricotPhase3Time: '2020-12-05T05:00:00Z', | ||
apricotPhase4Time: '2020-12-05T05:00:00Z', | ||
apricotPhase4MinPChainHeight: 0, | ||
apricotPhase5Time: '2020-12-05T05:00:00Z', | ||
apricotPhasePre6Time: '2020-12-05T05:00:00Z', | ||
apricotPhase6Time: '2020-12-05T05:00:00Z', | ||
apricotPhasePost6Time: '2020-12-05T05:00:00Z', | ||
banffTime: '2020-12-05T05:00:00Z', | ||
cortinaTime: '2020-12-05T05:00:00Z', | ||
cortinaXChainStopVertexID: '11111111111111111111111111111111LpoYY', | ||
durangoTime: '2020-12-05T05:00:00Z', | ||
etnaTime: '2020-12-05T05:00:00Z', | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { GetUpgradesInfoResponse } from '../info/model'; | ||
|
||
export const isEtnaEnabled = ( | ||
upgradesInfo: GetUpgradesInfoResponse, | ||
): boolean => { | ||
const { etnaTime } = upgradesInfo; | ||
return new Date(etnaTime) < new Date(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
import { testAddress1, testAddress2 } from '../fixtures/vms'; | ||
import { testContext } from '../fixtures/context'; | ||
import { Utxo } from '../serializable/avax/utxo'; | ||
import { utxoId } from '../fixtures/avax'; | ||
import { Address, Id } from '../serializable/fxs/common'; | ||
import { OutputOwners, TransferOutput } from '../serializable/fxs/secp256k1'; | ||
import { BigIntPr, Int } from '../serializable/primitives'; | ||
import { | ||
newBaseTx as avmBaseTx, | ||
newExportTx as avmExportTx, | ||
newImportTx as avmImportTx, | ||
} from '../vms/avm'; | ||
import { | ||
newBaseTx as pvmBaseTx, | ||
newExportTx as pvmExportTx, | ||
newImportTx as pvmImportTx, | ||
newCreateSubnetTx, | ||
newCreateBlockchainTx, | ||
newAddSubnetValidatorTx, | ||
newAddPermissionlessValidatorTx, | ||
newAddPermissionlessDelegatorTx, | ||
newRemoveSubnetValidatorTx, | ||
newTransferSubnetOwnershipTx, | ||
} from '../vms/pvm'; | ||
import { TransferableOutput } from '../serializable'; | ||
import { nodeId } from '../fixtures/common'; | ||
import { feeState as testFeeState } from '../fixtures/pvm'; | ||
import { testSubnetId } from '../fixtures/transactions'; | ||
import { blsPublicKeyBytes, blsSignatureBytes } from '../fixtures/primitives'; | ||
import { validateAvaxBurnedAmountEtna } from './validateAvaxBurnedAmountEtna'; | ||
|
||
const incorrectBurnedAmount = 1n; | ||
const correctBurnedAmount = 1000000n; | ||
|
||
const utxoMock = new Utxo( | ||
utxoId(), | ||
Id.fromString(testContext.avaxAssetID), | ||
new TransferOutput( | ||
new BigIntPr(1000000000000n), | ||
new OutputOwners(new BigIntPr(0n), new Int(1), [ | ||
Address.fromBytes(testAddress1)[0], | ||
]), | ||
), | ||
); | ||
|
||
const outputMock = new TransferableOutput( | ||
Id.fromString(testContext.avaxAssetID), | ||
new TransferOutput( | ||
new BigIntPr(100000000n), | ||
new OutputOwners(new BigIntPr(0n), new Int(1), [ | ||
Address.fromBytes(testAddress2)[0], | ||
]), | ||
), | ||
); | ||
|
||
describe('validateAvaxBurnedAmountEtna', () => { | ||
describe('unsupported tx types post-enta', () => { | ||
const unsupportedTestData = [ | ||
{ | ||
name: 'base tx on X', | ||
unsignedTx: avmBaseTx( | ||
testContext, | ||
[testAddress1], | ||
[utxoMock], | ||
[outputMock], | ||
), | ||
}, | ||
{ | ||
name: 'export from X', | ||
unsignedTx: avmExportTx( | ||
testContext, | ||
'P', | ||
[testAddress1], | ||
[utxoMock], | ||
[outputMock], | ||
), | ||
}, | ||
{ | ||
name: 'import from X', | ||
unsignedTx: avmImportTx( | ||
testContext, | ||
'P', | ||
[utxoMock], | ||
[testAddress2], | ||
[testAddress1], | ||
), | ||
}, | ||
]; | ||
describe.each(unsupportedTestData)('$name', ({ unsignedTx }) => { | ||
it('throws an error if tx type is not supported', () => { | ||
try { | ||
validateAvaxBurnedAmountEtna({ | ||
unsignedTx, | ||
context: testContext, | ||
burnedAmount: correctBurnedAmount, | ||
feeState: testFeeState(), | ||
}); | ||
} catch (error) { | ||
expect((error as Error).message).toEqual( | ||
'Unsupported transaction type.', | ||
); | ||
} | ||
}); | ||
}); | ||
}); | ||
|
||
const testData = [ | ||
{ | ||
name: 'base tx on P', | ||
unsignedTx: pvmBaseTx( | ||
testContext, | ||
[testAddress1], | ||
[utxoMock], | ||
[outputMock], | ||
), | ||
}, | ||
{ | ||
name: 'export from P', | ||
unsignedTx: pvmExportTx( | ||
testContext, | ||
'C', | ||
[testAddress1], | ||
[utxoMock], | ||
[outputMock], | ||
), | ||
}, | ||
{ | ||
name: 'import to P', | ||
unsignedTx: pvmImportTx( | ||
testContext, | ||
'C', | ||
[utxoMock], | ||
[testAddress2], | ||
[testAddress1], | ||
), | ||
}, | ||
{ | ||
name: 'create subnet', | ||
unsignedTx: newCreateSubnetTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
[testAddress1], | ||
), | ||
}, | ||
{ | ||
name: 'create blockchain', | ||
unsignedTx: newCreateBlockchainTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
'subnet', | ||
'chain', | ||
'vm', | ||
['fx1', 'fx2'], | ||
{}, | ||
[0], | ||
), | ||
}, | ||
{ | ||
name: 'add subnet validator', | ||
unsignedTx: newAddSubnetValidatorTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
nodeId().toString(), | ||
0n, | ||
1n, | ||
2n, | ||
'subnet', | ||
[0], | ||
), | ||
}, | ||
{ | ||
name: 'remove subnet validator', | ||
unsignedTx: newRemoveSubnetValidatorTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
nodeId().toString(), | ||
Id.fromHex(testSubnetId).toString(), | ||
[0], | ||
), | ||
}, | ||
{ | ||
name: 'add permissionless validator (subnet)', | ||
unsignedTx: newAddPermissionlessValidatorTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
nodeId().toString(), | ||
Id.fromHex(testSubnetId).toString(), | ||
0n, | ||
120n, | ||
1800000n, | ||
[], | ||
[], | ||
1, | ||
{}, | ||
1, | ||
0n, | ||
blsPublicKeyBytes(), | ||
blsSignatureBytes(), | ||
), | ||
}, | ||
{ | ||
name: 'add permissionless delegator (subnet)', | ||
unsignedTx: newAddPermissionlessDelegatorTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
nodeId().toString(), | ||
Id.fromHex(testSubnetId).toString(), | ||
0n, | ||
120n, | ||
1800000n, | ||
[], | ||
{}, | ||
1, | ||
0n, | ||
), | ||
}, | ||
{ | ||
name: 'transfer subnet ownership', | ||
unsignedTx: newTransferSubnetOwnershipTx( | ||
testContext, | ||
[utxoMock], | ||
[testAddress1], | ||
Id.fromHex(testSubnetId).toString(), | ||
[0, 2], | ||
[testAddress2], | ||
), | ||
}, | ||
]; | ||
|
||
describe.each(testData)('$name', ({ unsignedTx }) => { | ||
it('returns true if burned amount is correct', () => { | ||
const result = validateAvaxBurnedAmountEtna({ | ||
unsignedTx, | ||
context: testContext, | ||
burnedAmount: correctBurnedAmount, | ||
feeState: testFeeState(), | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
isValid: true, | ||
txFee: correctBurnedAmount, | ||
}); | ||
}); | ||
|
||
it('returns false if burned amount is not correct', () => { | ||
const result = validateAvaxBurnedAmountEtna({ | ||
unsignedTx, | ||
context: testContext, | ||
burnedAmount: incorrectBurnedAmount, | ||
feeState: { ...testFeeState(), price: 10_000n }, | ||
}); | ||
|
||
expect(result).toStrictEqual({ | ||
isValid: false, | ||
txFee: incorrectBurnedAmount, | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import type { Context } from '../vms/context/model'; | ||
import { | ||
isAddPermissionlessDelegatorTx, | ||
isAddPermissionlessValidatorTx, | ||
isAddSubnetValidatorTx, | ||
isCreateChainTx, | ||
isCreateSubnetTx, | ||
isPvmBaseTx, | ||
isExportTx as isPvmExportTx, | ||
isImportTx as isPvmImportTx, | ||
isRemoveSubnetValidatorTx, | ||
isTransferSubnetOwnershipTx, | ||
} from '../serializable/pvm'; | ||
import type { UnsignedTx } from '../vms/common'; | ||
import type { FeeState } from '../vms/pvm'; | ||
import { calculateFee } from '../vms/pvm/txs/fee/calculator'; | ||
|
||
export const validateAvaxBurnedAmountEtna = ({ | ||
unsignedTx, | ||
context, | ||
burnedAmount, | ||
feeState, | ||
}: { | ||
unsignedTx: UnsignedTx; | ||
context: Context; | ||
burnedAmount: bigint; | ||
feeState: FeeState; | ||
}): { isValid: boolean; txFee: bigint } => { | ||
const tx = unsignedTx.getTx(); | ||
|
||
const expectedFee = calculateFee( | ||
unsignedTx.getTx(), | ||
context.platformFeeConfig.weights, | ||
feeState.price < context.platformFeeConfig.minPrice | ||
? context.platformFeeConfig.minPrice | ||
: feeState.price, | ||
); | ||
|
||
if ( | ||
isPvmBaseTx(tx) || | ||
isPvmExportTx(tx) || | ||
isPvmImportTx(tx) || | ||
isAddPermissionlessValidatorTx(tx) || | ||
isAddPermissionlessDelegatorTx(tx) || | ||
isAddSubnetValidatorTx(tx) || | ||
isCreateChainTx(tx) || | ||
isCreateSubnetTx(tx) || | ||
isRemoveSubnetValidatorTx(tx) || | ||
isTransferSubnetOwnershipTx(tx) | ||
) { | ||
return { | ||
isValid: burnedAmount >= expectedFee, | ||
txFee: burnedAmount, | ||
}; | ||
} | ||
|
||
throw new Error(`tx type is not supported`); | ||
}; |
Oops, something went wrong.