From 1136e58de7bd846efccf43f6cedef030dbbcc70f Mon Sep 17 00:00:00 2001 From: Amir Bandeali Date: Mon, 4 Mar 2019 15:47:33 -0800 Subject: [PATCH] Add txOrigin to approvals --- .../src/MixinCoordinatorApprovalVerifier.sol | 29 +- .../contracts/src/MixinCoordinatorCore.sol | 3 + .../ICoordinatorApprovalVerifier.sol | 4 + .../src/interfaces/ICoordinatorCore.sol | 2 + .../src/libs/LibCoordinatorApproval.sol | 16 +- contracts/coordinator/test/coordinator.ts | 62 +++- contracts/coordinator/test/libs.ts | 8 +- contracts/coordinator/test/mixins.ts | 283 ++++++++++++++---- .../test/utils/approval_factory.ts | 8 +- contracts/coordinator/test/utils/constants.ts | 1 + .../coordinator/test/utils/hash_utils.ts | 15 +- contracts/coordinator/test/utils/types.ts | 1 + 12 files changed, 343 insertions(+), 89 deletions(-) diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol index 162d74567f..90b01cfc58 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorApprovalVerifier.sol @@ -43,11 +43,13 @@ contract MixinCoordinatorApprovalVerifier is /// @dev Validates that the 0x transaction has been approved by all of the feeRecipients /// that correspond to each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures @@ -64,6 +66,7 @@ contract MixinCoordinatorApprovalVerifier is assertValidTransactionOrdersApproval( transaction, orders, + txOrigin, transactionSignature, approvalExpirationTimeSeconds, approvalSignatures @@ -74,12 +77,14 @@ contract MixinCoordinatorApprovalVerifier is /// @dev Validates that the feeRecipients of a batch of order have approved a 0x transaction. /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param orders Array of order structs containing order specifications. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order. function assertValidTransactionOrdersApproval( LibZeroExTransaction.ZeroExTransaction memory transaction, LibOrder.Order[] memory orders, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures @@ -87,6 +92,12 @@ contract MixinCoordinatorApprovalVerifier is public view { + // Verify that Ethereum tx signer is the same as the approved txOrigin + require( + tx.origin == txOrigin, + "INVALID_SENDER" + ); + // Hash 0x transaction bytes32 transactionHash = getTransactionHash(transaction); @@ -98,6 +109,7 @@ contract MixinCoordinatorApprovalVerifier is // Create approval message uint256 currentApprovalExpirationTimeSeconds = approvalExpirationTimeSeconds[i]; CoordinatorApproval memory approval = CoordinatorApproval({ + txOrigin: txOrigin, transactionHash: transactionHash, transactionSignature: transactionSignature, approvalExpirationTimeSeconds: currentApprovalExpirationTimeSeconds @@ -117,6 +129,9 @@ contract MixinCoordinatorApprovalVerifier is // Add approval signer to list of signers approvalSignerAddresses = approvalSignerAddresses.append(approvalSignerAddress); } + + // Ethereum transaction signer gives implicit signature of approval + approvalSignerAddresses = approvalSignerAddresses.append(tx.origin); uint256 ordersLength = orders.length; for (uint256 i = 0; i < ordersLength; i++) { @@ -124,26 +139,14 @@ contract MixinCoordinatorApprovalVerifier is if (orders[i].senderAddress == address(0)) { continue; } - - // Ethereum transaction signer gives implicit signature of approval - address approverAddress = orders[i].feeRecipientAddress; - if (approverAddress == tx.origin) { - approvalSignerAddresses = approvalSignerAddresses.append(tx.origin); - continue; - } // Ensure feeRecipient of order has approved this 0x transaction + address approverAddress = orders[i].feeRecipientAddress; bool isOrderApproved = approvalSignerAddresses.contains(approverAddress); require( isOrderApproved, "INVALID_APPROVAL_SIGNATURE" ); - - // The Ethereum transaction signer must be the 0x transaction signer or an approver of the 0x transaction - require( - transaction.signerAddress == tx.origin || approvalSignerAddresses.contains(tx.origin), - "INVALID_SENDER" - ); } } diff --git a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol index 8de0879405..d5337bfbf2 100644 --- a/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/MixinCoordinatorCore.sol @@ -32,11 +32,13 @@ contract MixinCoordinatorCore is { /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures @@ -46,6 +48,7 @@ contract MixinCoordinatorCore is // Validate that the 0x transaction has been approves by each feeRecipient assertValidCoordinatorApprovals( transaction, + txOrigin, transactionSignature, approvalExpirationTimeSeconds, approvalSignatures diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol index aa8ec8bad5..f8cee23faa 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorApprovalVerifier.sol @@ -28,11 +28,13 @@ contract ICoordinatorApprovalVerifier { /// @dev Validates that the 0x transaction has been approved by all of the feeRecipients /// that correspond to each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. function assertValidCoordinatorApprovals( LibZeroExTransaction.ZeroExTransaction memory transaction, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures @@ -43,12 +45,14 @@ contract ICoordinatorApprovalVerifier { /// @dev Validates that the feeRecipients of a batch of order have approved a 0x transaction. /// @param transaction 0x transaction containing salt, signerAddress, and data. /// @param orders Array of order structs containing order specifications. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order. function assertValidTransactionOrdersApproval( LibZeroExTransaction.ZeroExTransaction memory transaction, LibOrder.Order[] memory orders, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures diff --git a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol index 4da0fa7a4d..bd7dded956 100644 --- a/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol +++ b/contracts/coordinator/contracts/src/interfaces/ICoordinatorCore.sol @@ -26,11 +26,13 @@ contract ICoordinatorCore { /// @dev Executes a 0x transaction that has been signed by the feeRecipients that correspond to each order in the transaction's Exchange calldata. /// @param transaction 0x transaction containing salt, signerAddress, and data. + /// @param txOrigin Required signer of Ethereum transaction calling this function. /// @param transactionSignature Proof that the transaction has been signed by the signer. /// @param approvalExpirationTimeSeconds Array of expiration times in seconds for which each corresponding approval signature expires. /// @param approvalSignatures Array of signatures that correspond to the feeRecipients of each order in the transaction's Exchange calldata. function executeTransaction( LibZeroExTransaction.ZeroExTransaction memory transaction, + address txOrigin, bytes memory transactionSignature, uint256[] memory approvalExpirationTimeSeconds, bytes[] memory approvalSignatures diff --git a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol index 5ac640b21a..591ff18d32 100644 --- a/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol +++ b/contracts/coordinator/contracts/src/libs/LibCoordinatorApproval.sol @@ -27,14 +27,16 @@ contract LibCoordinatorApproval is // Hash for the EIP712 Coordinator approval message // keccak256(abi.encodePacked( // "CoordinatorApproval(", + // "address txOrigin,", // "bytes32 transactionHash,", // "bytes transactionSignature,", // "uint256 approvalExpirationTimeSeconds", // ")" // )); - bytes32 constant internal EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = 0x9f6a55727f39e17015e248e6457fbf0b18270e56c53093ff432d3db5703e191e; + bytes32 constant internal EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH = 0x2fbcdbaa76bc7589916958ae919dfbef04d23f6bbf26de6ff317b32c6cc01e05; struct CoordinatorApproval { + address txOrigin; // Required signer of Ethereum transaction that is submitting approval. bytes32 transactionHash; // EIP712 hash of the transaction, using the domain separator of this contract. bytes transactionSignature; // Signature of the 0x transaction. uint256 approvalExpirationTimeSeconds; // Timestamp in seconds for which the signature expires. @@ -62,6 +64,7 @@ contract LibCoordinatorApproval is { bytes32 schemaHash = EIP712_COORDINATOR_APPROVAL_SCHEMA_HASH; bytes memory transactionSignature = approval.transactionSignature; + address txOrigin = approval.txOrigin; bytes32 transactionHash = approval.transactionHash; uint256 approvalExpirationTimeSeconds = approval.approvalExpirationTimeSeconds; @@ -80,12 +83,13 @@ contract LibCoordinatorApproval is // Load free memory pointer let memPtr := mload(64) - mstore(memPtr, schemaHash) // hash of schema - mstore(add(memPtr, 32), transactionHash) // transactionHash - mstore(add(memPtr, 64), transactionSignatureHash) // transactionSignatureHash - mstore(add(memPtr, 96), approvalExpirationTimeSeconds) // approvalExpirationTimeSeconds + mstore(memPtr, schemaHash) // hash of schema + mstore(add(memPtr, 32), txOrigin) // txOrigin + mstore(add(memPtr, 64), transactionHash) // transactionHash + mstore(add(memPtr, 96), transactionSignatureHash) // transactionSignatureHash + mstore(add(memPtr, 128), approvalExpirationTimeSeconds) // approvalExpirationTimeSeconds // Compute hash - result := keccak256(memPtr, 128) + result := keccak256(memPtr, 160) } return result; } diff --git a/contracts/coordinator/test/coordinator.ts b/contracts/coordinator/test/coordinator.ts index 03b39616d5..c33a15f549 100644 --- a/contracts/coordinator/test/coordinator.ts +++ b/contracts/coordinator/test/coordinator.ts @@ -126,10 +126,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -161,6 +166,7 @@ describe('Coordinator tests', () => { const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + feeRecipientAddress, transaction.signature, [], [], @@ -192,6 +198,7 @@ describe('Coordinator tests', () => { await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [], [], @@ -209,11 +216,16 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -228,10 +240,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -246,10 +263,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -268,10 +290,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -305,6 +332,7 @@ describe('Coordinator tests', () => { const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + feeRecipientAddress, transaction.signature, [], [], @@ -337,11 +365,16 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -356,10 +389,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -374,10 +412,15 @@ describe('Coordinator tests', () => { const transaction = takerTransactionFactory.newSignedTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory.newSignedApproval( + transaction, + takerAddress, + approvalExpirationTimeSeconds, + ); await expectTransactionFailedAsync( coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + takerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -396,6 +439,7 @@ describe('Coordinator tests', () => { const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + makerAddress, transaction.signature, [], [], @@ -423,6 +467,7 @@ describe('Coordinator tests', () => { const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + makerAddress, transaction.signature, [], [], @@ -452,6 +497,7 @@ describe('Coordinator tests', () => { const transactionReceipt = await web3Wrapper.awaitTransactionSuccessAsync( await coordinatorContract.executeTransaction.sendTransactionAsync( transaction, + makerAddress, transaction.signature, [], [], diff --git a/contracts/coordinator/test/libs.ts b/contracts/coordinator/test/libs.ts index 9573ba15c2..4833a70850 100644 --- a/contracts/coordinator/test/libs.ts +++ b/contracts/coordinator/test/libs.ts @@ -52,12 +52,18 @@ describe('Libs tests', () => { signature: '0x5678', }; const approvalExpirationTimeSeconds = new BigNumber(0); + const txOrigin = constants.NULL_ADDRESS; const approval = { + txOrigin, transactionHash: hashUtils.getTransactionHashHex(signedTx), transactionSignature: signedTx.signature, approvalExpirationTimeSeconds, }; - const expectedApprovalHash = hashUtils.getApprovalHashHex(signedTx, approvalExpirationTimeSeconds); + const expectedApprovalHash = hashUtils.getApprovalHashHex( + signedTx, + txOrigin, + approvalExpirationTimeSeconds, + ); const approvalHash = await testLibs.publicGetCoordinatorApprovalHash.callAsync(approval); expect(expectedApprovalHash).to.eq(approvalHash); }); diff --git a/contracts/coordinator/test/mixins.ts b/contracts/coordinator/test/mixins.ts index 84d69b8e4b..dc2baffecf 100644 --- a/contracts/coordinator/test/mixins.ts +++ b/contracts/coordinator/test/mixins.ts @@ -137,10 +137,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -148,6 +153,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -164,10 +170,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -175,6 +186,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -188,14 +200,22 @@ describe('Mixins tests', () => { await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, transaction.signature, [], [], { from: approvalSignerAddress1 }, ); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: approvalSignerAddress1, - }); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + approvalSignerAddress1, + transaction.signature, + [], + [], + { + from: approvalSignerAddress1, + }, + ); }); it(`Should be successful: function=${fnName}, caller=approver1, senderAddress=[verifier], approval_sig=[approver1], expiration=[invalid]`, async () => { const orders = [defaultOrder]; @@ -203,10 +223,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -214,6 +239,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -227,14 +253,22 @@ describe('Mixins tests', () => { await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, transaction.signature, [], [], { from: approvalSignerAddress1 }, ); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: approvalSignerAddress1, - }); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + approvalSignerAddress1, + transaction.signature, + [], + [], + { + from: approvalSignerAddress1, + }, + ); }); it(`Should revert: function=${fnName}, caller=tx_signer, senderAddress=[verifier], approval_sig=[invalid], expiration=[valid]`, async () => { const orders = [defaultOrder]; @@ -242,12 +276,17 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -258,6 +297,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -272,11 +312,16 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -287,6 +332,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -301,11 +347,16 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -316,6 +367,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -338,10 +390,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -349,6 +406,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -364,10 +422,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -375,6 +438,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -391,14 +455,20 @@ describe('Mixins tests', () => { await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, transaction.signature, [], [], { from: transactionSignerAddress }, ); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: transactionSignerAddress, - }); }); it(`Should be successful: function=${fnName} caller=tx_signer, senderAddress=[verifier,null], feeRecipient=[approver1,approver1], approval_sig=[approver1], expiration=[valid]`, async () => { const orders = [defaultOrder, { ...defaultOrder, senderAddress: devConstants.NULL_ADDRESS }]; @@ -406,10 +476,15 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -417,6 +492,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval.signature], @@ -429,11 +505,20 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval1 = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); + const approval2 = approvalFactory2.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approval2.signature], @@ -441,6 +526,7 @@ describe('Mixins tests', () => { ); await mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approval2.signature], @@ -454,36 +540,54 @@ describe('Mixins tests', () => { await mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, + transaction.signature, + [], + [], + { from: approvalSignerAddress1 }, + ); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + approvalSignerAddress1, transaction.signature, [], [], { from: approvalSignerAddress1 }, ); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: approvalSignerAddress1, - }); }); - it(`Should be successful: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => { + it(`Should revert: function=${fnName} caller=approver1, senderAddress=[verifier,verifier], feeRecipient=[approver1,approver2], approval_sig=[approver2], expiration=[valid]`, async () => { const orders = [defaultOrder, { ...defaultOrder, feeRecipientAddress: approvalSignerAddress2 }]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(fnName, orders); const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); - await mixins.assertValidTransactionOrdersApproval.callAsync( + const approval2 = approvalFactory2.newSignedApproval( transaction, - orders, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval2.signature], - { from: approvalSignerAddress1 }, + transactionSignerAddress, + approvalExpirationTimeSeconds, ); - await mixins.assertValidCoordinatorApprovals.callAsync( - transaction, - transaction.signature, - [approvalExpirationTimeSeconds], - [approval2.signature], - { from: approvalSignerAddress1 }, + expectContractCallFailedAsync( + mixins.assertValidTransactionOrdersApproval.callAsync( + transaction, + orders, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval2.signature], + { from: approvalSignerAddress1 }, + ), + RevertReason.InvalidSender, + ); + expectContractCallFailedAsync( + mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [approvalExpirationTimeSeconds], + [approval2.signature], + { from: approvalSignerAddress1 }, + ), + RevertReason.InvalidSender, ); }); it(`Should revert: function=${fnName} caller=tx_signer, senderAddress=[verifier,verifier], feeRecipient=[approver1, approver1], approval_sig=[], expiration=[]`, async () => { @@ -494,6 +598,7 @@ describe('Mixins tests', () => { mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [], [], @@ -502,9 +607,14 @@ describe('Mixins tests', () => { RevertReason.InvalidApprovalSignature, ); expectContractCallFailedAsync( - mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: transactionSignerAddress, - }), + mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ), RevertReason.InvalidApprovalSignature, ); }); @@ -514,12 +624,17 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); const signature = `${approval.signature.slice(0, 4)}FFFFFFFF${approval.signature.slice(12)}`; expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -530,6 +645,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [signature], @@ -544,13 +660,22 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval1 = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); + const approval2 = approvalFactory2.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approvalSignature2], @@ -561,6 +686,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds, approvalExpirationTimeSeconds], [approval1.signature, approvalSignature2], @@ -575,12 +701,17 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval2 = approvalFactory2.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); const approvalSignature2 = `${approval2.signature.slice(0, 4)}FFFFFFFF${approval2.signature.slice(12)}`; expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approvalSignature2], @@ -591,6 +722,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approvalSignature2], @@ -606,12 +738,21 @@ describe('Mixins tests', () => { const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds1 = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); const approvalExpirationTimeSeconds2 = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds1); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds2); + const approval1 = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds1, + ); + const approval2 = approvalFactory2.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds2, + ); expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2], [approval1.signature, approval2.signature], @@ -622,6 +763,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds1, approvalExpirationTimeSeconds2], [approval1.signature, approval2.signature], @@ -636,11 +778,16 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).minus(constants.TIME_BUFFER); - const approval2 = approvalFactory2.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval2 = approvalFactory2.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approval2.signature], @@ -651,6 +798,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + approvalSignerAddress1, transaction.signature, [approvalExpirationTimeSeconds], [approval2.signature], @@ -665,11 +813,16 @@ describe('Mixins tests', () => { const transaction = transactionFactory.newSignedCoordinatorTransaction(data); const currentTimestamp = await getLatestBlockTimestampAsync(); const approvalExpirationTimeSeconds = new BigNumber(currentTimestamp).plus(constants.TIME_BUFFER); - const approval1 = approvalFactory1.newSignedApproval(transaction, approvalExpirationTimeSeconds); + const approval1 = approvalFactory1.newSignedApproval( + transaction, + transactionSignerAddress, + approvalExpirationTimeSeconds, + ); expectContractCallFailedAsync( mixins.assertValidTransactionOrdersApproval.callAsync( transaction, orders, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval1.signature], @@ -680,6 +833,7 @@ describe('Mixins tests', () => { expectContractCallFailedAsync( mixins.assertValidCoordinatorApprovals.callAsync( transaction, + transactionSignerAddress, transaction.signature, [approvalExpirationTimeSeconds], [approval1.signature], @@ -695,25 +849,40 @@ describe('Mixins tests', () => { const orders = [defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS, orders); const transaction = transactionFactory.newSignedCoordinatorTransaction(data); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: transactionSignerAddress, - }); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ); }); it('should allow the tx signer to call `batchCancelOrders` without approval', async () => { const orders = [defaultOrder, defaultOrder]; const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.BATCH_CANCEL_ORDERS, orders); const transaction = transactionFactory.newSignedCoordinatorTransaction(data); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: transactionSignerAddress, - }); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ); }); it('should allow the tx signer to call `cancelOrdersUpTo` without approval', async () => { const orders: SignedOrder[] = []; const data = exchangeDataEncoder.encodeOrdersToExchangeData(constants.CANCEL_ORDERS_UP_TO, orders); const transaction = transactionFactory.newSignedCoordinatorTransaction(data); - await mixins.assertValidCoordinatorApprovals.callAsync(transaction, transaction.signature, [], [], { - from: transactionSignerAddress, - }); + await mixins.assertValidCoordinatorApprovals.callAsync( + transaction, + transactionSignerAddress, + transaction.signature, + [], + [], + { from: transactionSignerAddress }, + ); }); }); }); diff --git a/contracts/coordinator/test/utils/approval_factory.ts b/contracts/coordinator/test/utils/approval_factory.ts index f364cd95ff..e861214110 100644 --- a/contracts/coordinator/test/utils/approval_factory.ts +++ b/contracts/coordinator/test/utils/approval_factory.ts @@ -13,6 +13,7 @@ export class ApprovalFactory { } public newSignedApproval( transaction: SignedZeroExTransaction, + txOrigin: string, approvalExpirationTimeSeconds: BigNumber, signatureType: CoordinatorSignatureType = CoordinatorSignatureType.EthSign, ): SignedCoordinatorApproval { @@ -20,9 +21,14 @@ export class ApprovalFactory { ...transaction, verifyingContractAddress: this._verifyingContractAddress, }; - const approvalHashBuff = hashUtils.getApprovalHashBuffer(coordinatorTransaction, approvalExpirationTimeSeconds); + const approvalHashBuff = hashUtils.getApprovalHashBuffer( + coordinatorTransaction, + txOrigin, + approvalExpirationTimeSeconds, + ); const signatureBuff = signingUtils.signMessage(approvalHashBuff, this._privateKey, signatureType); const signedApproval = { + txOrigin, transaction: coordinatorTransaction, approvalExpirationTimeSeconds, signature: ethUtil.addHexPrefix(signatureBuff.toString('hex')), diff --git a/contracts/coordinator/test/utils/constants.ts b/contracts/coordinator/test/utils/constants.ts index 04c713b508..e2fc8bdbae 100644 --- a/contracts/coordinator/test/utils/constants.ts +++ b/contracts/coordinator/test/utils/constants.ts @@ -6,6 +6,7 @@ export const constants = { COORDINATOR_APPROVAL_SCHEMA: { name: 'CoordinatorApproval', parameters: [ + { name: 'txOrigin', type: 'address' }, { name: 'transactionHash', type: 'bytes32' }, { name: 'transactionSignature', type: 'bytes' }, { name: 'approvalExpirationTimeSeconds', type: 'uint256' }, diff --git a/contracts/coordinator/test/utils/hash_utils.ts b/contracts/coordinator/test/utils/hash_utils.ts index 6bd1c5dd54..094b73e7b6 100644 --- a/contracts/coordinator/test/utils/hash_utils.ts +++ b/contracts/coordinator/test/utils/hash_utils.ts @@ -7,7 +7,11 @@ import * as _ from 'lodash'; import { constants } from './index'; export const hashUtils = { - getApprovalHashBuffer(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): Buffer { + getApprovalHashBuffer( + transaction: SignedZeroExTransaction, + txOrigin: string, + approvalExpirationTimeSeconds: BigNumber, + ): Buffer { const domain = { name: constants.COORDINATOR_DOMAIN_NAME, version: constants.COORDINATOR_DOMAIN_VERSION, @@ -15,6 +19,7 @@ export const hashUtils = { }; const transactionHash = hashUtils.getTransactionHashHex(transaction); const approval = { + txOrigin, transactionHash, transactionSignature: transaction.signature, approvalExpirationTimeSeconds: approvalExpirationTimeSeconds.toString(), @@ -30,9 +35,13 @@ export const hashUtils = { const hashBuffer = signTypedDataUtils.generateTypedDataHash(typedData); return hashBuffer; }, - getApprovalHashHex(transaction: SignedZeroExTransaction, approvalExpirationTimeSeconds: BigNumber): string { + getApprovalHashHex( + transaction: SignedZeroExTransaction, + txOrigin: string, + approvalExpirationTimeSeconds: BigNumber, + ): string { const hashHex = `0x${hashUtils - .getApprovalHashBuffer(transaction, approvalExpirationTimeSeconds) + .getApprovalHashBuffer(transaction, txOrigin, approvalExpirationTimeSeconds) .toString('hex')}`; return hashHex; }, diff --git a/contracts/coordinator/test/utils/types.ts b/contracts/coordinator/test/utils/types.ts index 822d2795cc..5db1a847bd 100644 --- a/contracts/coordinator/test/utils/types.ts +++ b/contracts/coordinator/test/utils/types.ts @@ -3,6 +3,7 @@ import { BigNumber } from '@0x/utils'; export interface CoordinatorApproval { transaction: SignedZeroExTransaction; + txOrigin: string; approvalExpirationTimeSeconds: BigNumber; }