Skip to content

Commit

Permalink
alpha-1
Browse files Browse the repository at this point in the history
Signed-off-by: Logan Nguyen <[email protected]>
  • Loading branch information
quiet-node committed Apr 23, 2024
1 parent 231e3d5 commit 96e6c8a
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 5 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/acceptance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
pull_request:
branches: [main, release/**]
push:
branches: [main, release/**]
branches: [main, release/**, deterministic-back-up]
tags: [v*]

concurrency:
Expand All @@ -17,6 +17,7 @@ jobs:
uses: ./.github/workflows/acceptance-workflow.yml
with:
testfilter: api_batch1
networkTag: 0.49.1

api_batch_2:
name: API Batch 2
Expand Down Expand Up @@ -78,6 +79,7 @@ jobs:
with:
testfilter: ws
test_ws_server: true
networkTag: 0.49.1

cacheservice:
name: Cache Service
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
pull_request:
branches: [main, release/**]
push:
branches: [main, release/**]
branches: [main, release/**, deterministic-back-up]
tags: [v*]

concurrency:
Expand Down
2 changes: 0 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions packages/relay/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,10 @@ export default {
NEW_HEADS: 'newHeads',
NEW_PENDING_TRANSACTIONS: 'newPendingTransactions',
},

// @source: Foundry related constants below can be found at https://github.com/Arachnid/deterministic-deployment-proxy?tab=readme-ov-file#latest-outputs
DETERMINISTIC_DEPLOYER_TRANSACTION:
'0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222',
DETERMINISTIC_DEPLOYMENT_SIGNER: '0x3fab184622dc19b6109349b94811493bf2a45362',
DETERMINISTIC_PROXY_CONTRACT: '0x4e59b44847b379578588920ca78fbf26c0b4956c',
};
17 changes: 16 additions & 1 deletion packages/relay/src/lib/precheck.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ export class Precheck {
const requestIdPrefix = formatRequestIdMessage(requestId);
const minGasPrice = BigInt(gasPrice);
const txGasPrice = tx.gasPrice || tx.maxFeePerGas! + tx.maxPriorityFeePerGas!;
const passes = txGasPrice >= minGasPrice;

// **notice: Pass gasPrice precheck if txGasPrice is greater than the minimum network's gas price value,
// OR if the transaction is the deterministic deployment transaction (a special case).
// **explanation: The deterministic deployment transaction is pre-signed with a gasPrice value of only 10 hbars,
// which is lower than the minimum gas price value in all Hedera network environments. Therefore,
// this special case is exempt from the precheck in the Relay, and the gas price logic will be resolved at the Services level.
const passes = txGasPrice >= minGasPrice || Precheck.isDeterministicDeploymentTransaction(tx);

if (!passes) {
if (constants.GAS_PRICE_TINY_BAR_BUFFER) {
Expand All @@ -152,6 +158,15 @@ export class Precheck {
}
}

/**
* Checks if a transaction is the deterministic deployment transaction.
* @param {Transaction} tx - The transaction to check.
* @returns {boolean} Returns true if the transaction is the deterministic deployment transaction, otherwise false.
*/
static isDeterministicDeploymentTransaction(tx: Transaction): boolean {
return tx.serialized === constants.DETERMINISTIC_DEPLOYER_TRANSACTION;
}

/**
* @param tx
* @param callerName
Expand Down
25 changes: 25 additions & 0 deletions packages/relay/tests/lib/precheck.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,31 @@ describe('Precheck', async function () {
expect(result).to.not.exist;
});

it('should recognize if a signed raw transaction is the deterministic deployment transaction', async () => {
const parsedDeterministicDeploymentTransaction = ethers.Transaction.from(
constants.DETERMINISTIC_DEPLOYER_TRANSACTION,
);

expect(Precheck.isDeterministicDeploymentTransaction(parsedDeterministicDeploymentTransaction)).to.be.true;
});

it('Should recognize if a signed raw transaction is NOT the deterministic deployment transaction', async () => {
expect(Precheck.isDeterministicDeploymentTransaction(parsedtxWithChainId0x0)).to.be.false;
expect(Precheck.isDeterministicDeploymentTransaction(parsedTxWithMatchingChainId)).to.be.false;
expect(Precheck.isDeterministicDeploymentTransaction(parsedTxWithNonMatchingChainId)).to.be.false;
});

it('should pass for gas price if the transaction is the deterministic deployment transaction', async function () {
const parsedDeterministicDeploymentTransaction = ethers.Transaction.from(
constants.DETERMINISTIC_DEPLOYER_TRANSACTION,
);
const result = precheck.gasPrice(
parsedDeterministicDeploymentTransaction,
100 * constants.TINYBAR_TO_WEIBAR_COEF,
);
expect(result).to.not.exist;
});

it('should not pass for gas price not enough', async function () {
const minGasPrice = 1000 * constants.TINYBAR_TO_WEIBAR_COEF;
try {
Expand Down
55 changes: 55 additions & 0 deletions packages/server/tests/acceptance/rpc_batch1.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,61 @@ describe('@api-batch-1 RPC Server Acceptance Tests', function () {
await Assertions.assertPredefinedRpcError(error, sendRawTransaction, true, relay, [signedTx, requestId]);
});

it('should execute "eth_sendRawTransaction" for deterministic deployment transaction', async function () {
// @logic: since the DETERMINISTIC_DEPLOYER_TRANSACTION is a deterministic transaction hash which is signed
// by the DETERMINISTIC_DEPLOYMENT_SIGNER with tx.nonce = 0. With that reason, if the current nonce of the signer
// is not 0, it means the DETERMINISTIC_DEPLOYER_TRANSACTION has already been submitted, and the DETERMINISTIC_PROXY_CONTRACT
// has already been deployed to the network. Therefore, it only matters to test this flow once.
const signerNonce = await relay.getAccountNonce(constants.DETERMINISTIC_DEPLOYMENT_SIGNER, requestId);

if (signerNonce === 0) {
// send gas money to the proxy deployer
const sendHbarTx = {
...defaultLegacyTransactionData,
value: (10 * ONE_TINYBAR * 10 ** 8).toString(), // 10hbar - the gasPrice to deploy the deterministic proxy contract
to: constants.DETERMINISTIC_DEPLOYMENT_SIGNER,
nonce: await relay.getAccountNonce(accounts[2].address, requestId),
gasPrice: await relay.gasPrice(requestId),
};
const signedSendHbarTx = await accounts[2].wallet.signTransaction(sendHbarTx);
await relay.sendRawTransaction(signedSendHbarTx, requestId);
await new Promise((r) => setTimeout(r, 2000)); // wait for signer's account to propagate accross the network

const deployerBalance = await relay.getBalance(
constants.DETERMINISTIC_DEPLOYMENT_SIGNER,
'latest',
requestId,
);
expect(deployerBalance).to.not.eq(0);

// send transaction to deploy proxy transaction
const deterministicDeployTransactionHash = await relay.sendRawTransaction(
constants.DETERMINISTIC_DEPLOYER_TRANSACTION,
requestId,
);
const receipt = await mirrorNode.get(`/contracts/results/${deterministicDeployTransactionHash}`, requestId);

const fromAccountInfo = await global.mirrorNode.get(`/accounts/${receipt.from}`);
const toAccountInfo = await global.mirrorNode.get(`/accounts/${receipt.to}`);

expect(receipt).to.exist;
expect(fromAccountInfo.evm_address).to.eq(constants.DETERMINISTIC_DEPLOYMENT_SIGNER);
expect(toAccountInfo.evm_address).to.eq(constants.DETERMINISTIC_PROXY_CONTRACT);
expect(receipt.address).to.eq(constants.DETERMINISTIC_PROXY_CONTRACT);
} else {
try {
await relay.sendRawTransaction(constants.DETERMINISTIC_DEPLOYER_TRANSACTION, requestId);
expect(true).to.be.false;
} catch (error) {
const expectedNonceTooLowError = predefined.NONCE_TOO_LOW(0, signerNonce);
const errObj = JSON.parse(error.info.responseBody).error;
expect(errObj.code).to.eq(expectedNonceTooLowError.code);
expect(errObj.name).to.eq(expectedNonceTooLowError.name);
expect(errObj.message).to.contain(expectedNonceTooLowError.message);
}
}
});

it('@release should execute "eth_sendRawTransaction" for legacy EIP 155 transactions', async function () {
const receiverInitialBalance = await relay.getBalance(mirrorContract.evm_address, 'latest', requestId);
const transaction = {
Expand Down

0 comments on commit 96e6c8a

Please sign in to comment.