Implement sender abstraction
This commit is contained in:
@@ -24,13 +24,15 @@ import "./MixinSignatureValidator.sol";
|
||||
import "./MixinSettlement.sol";
|
||||
import "./MixinWrapperFunctions.sol";
|
||||
import "./MixinAssetProxyDispatcher.sol";
|
||||
import "./MixinTransactions.sol";
|
||||
|
||||
contract Exchange is
|
||||
MixinExchangeCore,
|
||||
MixinSignatureValidator,
|
||||
MixinSettlement,
|
||||
MixinWrapperFunctions,
|
||||
MixinAssetProxyDispatcher
|
||||
MixinAssetProxyDispatcher,
|
||||
MixinTransactions
|
||||
{
|
||||
string constant public VERSION = "2.0.1-alpha";
|
||||
|
||||
@@ -42,5 +44,6 @@ contract Exchange is
|
||||
MixinSettlement(_zrxProxyData)
|
||||
MixinWrapperFunctions()
|
||||
MixinAssetProxyDispatcher()
|
||||
MixinTransactions()
|
||||
{}
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ contract LibOrder {
|
||||
"address makerAddress",
|
||||
"address takerAddress",
|
||||
"address feeRecipientAddress",
|
||||
"address senderAddress",
|
||||
"uint256 makerAssetAmount",
|
||||
"uint256 takerAssetAmount",
|
||||
"uint256 makerFee",
|
||||
@@ -40,6 +41,7 @@ contract LibOrder {
|
||||
address makerAddress;
|
||||
address takerAddress;
|
||||
address feeRecipientAddress;
|
||||
address senderAddress;
|
||||
uint256 makerAssetAmount;
|
||||
uint256 takerAssetAmount;
|
||||
uint256 makerFee;
|
||||
@@ -66,6 +68,7 @@ contract LibOrder {
|
||||
order.makerAddress,
|
||||
order.takerAddress,
|
||||
order.feeRecipientAddress,
|
||||
order.senderAddress,
|
||||
order.makerAssetAmount,
|
||||
order.takerAssetAmount,
|
||||
order.makerFee,
|
||||
|
@@ -18,10 +18,12 @@
|
||||
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
pragma experimental "v0.5.0";
|
||||
|
||||
import "./mixins/MExchangeCore.sol";
|
||||
import "./mixins/MSettlement.sol";
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
||||
import "./LibOrder.sol";
|
||||
import "./LibErrors.sol";
|
||||
import "./LibPartialAmount.sol";
|
||||
@@ -35,6 +37,7 @@ contract MixinExchangeCore is
|
||||
MExchangeCore,
|
||||
MSettlement,
|
||||
MSignatureValidator,
|
||||
MTransactions,
|
||||
SafeMath,
|
||||
LibErrors,
|
||||
LibPartialAmount
|
||||
@@ -113,10 +116,16 @@ contract MixinExchangeCore is
|
||||
require(order.takerAssetAmount > 0);
|
||||
require(isValidSignature(orderHash, order.makerAddress, signature));
|
||||
}
|
||||
|
||||
// Validate sender
|
||||
if (order.senderAddress != address(0)) {
|
||||
require(order.senderAddress == msg.sender);
|
||||
}
|
||||
|
||||
// Validate taker
|
||||
// Validate transaction signed by taker
|
||||
address takerAddress = getSignerAddress();
|
||||
if (order.takerAddress != address(0)) {
|
||||
require(order.takerAddress == msg.sender);
|
||||
require(order.takerAddress == takerAddress);
|
||||
}
|
||||
require(takerAssetFillAmount > 0);
|
||||
|
||||
@@ -146,21 +155,10 @@ contract MixinExchangeCore is
|
||||
|
||||
// Settle order
|
||||
(fillResults.makerAssetFilledAmount, fillResults.makerFeePaid, fillResults.takerFeePaid) =
|
||||
settleOrder(order, msg.sender, fillResults.takerAssetFilledAmount);
|
||||
settleOrder(order, takerAddress, fillResults.takerAssetFilledAmount);
|
||||
|
||||
// Log order
|
||||
emit Fill(
|
||||
order.makerAddress,
|
||||
msg.sender,
|
||||
order.feeRecipientAddress,
|
||||
fillResults.makerAssetFilledAmount,
|
||||
fillResults.takerAssetFilledAmount,
|
||||
fillResults.makerFeePaid,
|
||||
fillResults.takerFeePaid,
|
||||
orderHash,
|
||||
order.makerAssetData,
|
||||
order.takerAssetData
|
||||
);
|
||||
emitFillEvent(order, takerAddress, orderHash, fillResults);
|
||||
return fillResults;
|
||||
}
|
||||
|
||||
@@ -178,8 +176,16 @@ contract MixinExchangeCore is
|
||||
// Validate the order
|
||||
require(order.makerAssetAmount > 0);
|
||||
require(order.takerAssetAmount > 0);
|
||||
require(order.makerAddress == msg.sender);
|
||||
|
||||
// Validate sender
|
||||
if (order.senderAddress != address(0)) {
|
||||
require(order.senderAddress == msg.sender);
|
||||
}
|
||||
|
||||
// Validate transaction signed by maker
|
||||
address makerAddress = getSignerAddress();
|
||||
require(order.makerAddress == makerAddress);
|
||||
|
||||
if (block.timestamp >= order.expirationTimeSeconds) {
|
||||
emit ExchangeError(uint8(Errors.ORDER_EXPIRED), orderHash);
|
||||
return false;
|
||||
@@ -233,4 +239,27 @@ contract MixinExchangeCore is
|
||||
isError = errPercentageTimes1000000 > 1000;
|
||||
return isError;
|
||||
}
|
||||
|
||||
/// @dev Logs a Fill event with the given arguments.
|
||||
/// The sole purpose of this function is to get around the stack variable limit.
|
||||
function emitFillEvent(
|
||||
Order memory order,
|
||||
address takerAddress,
|
||||
bytes32 orderHash,
|
||||
FillResults memory fillResults)
|
||||
internal
|
||||
{
|
||||
emit Fill(
|
||||
order.makerAddress,
|
||||
takerAddress,
|
||||
order.feeRecipientAddress,
|
||||
fillResults.makerAssetFilledAmount,
|
||||
fillResults.takerAssetFilledAmount,
|
||||
fillResults.makerFeePaid,
|
||||
fillResults.takerFeePaid,
|
||||
orderHash,
|
||||
order.makerAssetData,
|
||||
order.takerAssetData
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./mixins/MSignatureValidator.sol";
|
||||
import "./mixins/MTransactions.sol";
|
||||
|
||||
contract MixinTransactions is
|
||||
MSignatureValidator,
|
||||
MTransactions
|
||||
{
|
||||
|
||||
// Mapping of transaction hash => executed
|
||||
mapping (bytes32 => bool) public transactions;
|
||||
|
||||
// Address of current transaction signer
|
||||
address currentSigner;
|
||||
|
||||
/// @dev Executes an exchange method call in the context of signer.
|
||||
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
|
||||
/// @param signer Address of transaction signer.
|
||||
/// @param data AbiV2 encoded calldata.
|
||||
/// @param signature Proof of signer transaction by signer.
|
||||
function executeTransaction(
|
||||
uint256 salt,
|
||||
address signer,
|
||||
bytes data,
|
||||
bytes signature)
|
||||
external
|
||||
{
|
||||
// Prevent reentrancy
|
||||
require(currentSigner == address(0));
|
||||
|
||||
// Calculate transaction hash
|
||||
bytes32 transactionHash = keccak256(
|
||||
address(this),
|
||||
salt,
|
||||
data
|
||||
);
|
||||
|
||||
// Validate transaction has not been executed
|
||||
require(!transactions[transactionHash]);
|
||||
|
||||
// TODO: is SignatureType.Caller necessary if we make this check?
|
||||
if (signer != msg.sender) {
|
||||
// Validate signature
|
||||
require(isValidSignature(transactionHash, signer, signature));
|
||||
|
||||
// Set the current transaction signer
|
||||
currentSigner = signer;
|
||||
}
|
||||
|
||||
// Execute transaction
|
||||
transactions[transactionHash] = true;
|
||||
require(address(this).delegatecall(data));
|
||||
|
||||
// Reset current transaction signer
|
||||
currentSigner = address(0);
|
||||
}
|
||||
|
||||
function getSignerAddress()
|
||||
internal
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
address signerAddress = currentSigner == address(0) ? msg.sender : currentSigner;
|
||||
return signerAddress;
|
||||
}
|
||||
}
|
@@ -75,24 +75,25 @@ contract MixinWrapperFunctions is
|
||||
// | | 0x00 | | 1. offset to order (*) |
|
||||
// | | 0x20 | | 2. takerAssetFillAmount |
|
||||
// | | 0x40 | | 3. offset to signature (*) |
|
||||
// | Data | | 11 * 32 | order: |
|
||||
// | | 0x000 | | 1. makerAddress |
|
||||
// | | 0x020 | | 2. takerAddress |
|
||||
// | | 0x040 | | 3. feeRecipientAddress |
|
||||
// | | 0x060 | | 4. makerAssetAmount |
|
||||
// | | 0x080 | | 5. takerAssetAmount |
|
||||
// | | 0x0A0 | | 6. makerFeeAmount |
|
||||
// | | 0x0C0 | | 7. takerFeeAmount |
|
||||
// | | 0x0E0 | | 8. expirationTimeSeconds |
|
||||
// | | 0x100 | | 9. salt |
|
||||
// | | 0x120 | | 10. Offset to makerAssetProxyMetadata (*) |
|
||||
// | | 0x140 | | 11. Offset to takerAssetProxyMetadata (*) |
|
||||
// | | 0x160 | 32 | makerAssetProxyMetadata Length |
|
||||
// | | 0x180 | ** | makerAssetProxyMetadata Contents |
|
||||
// | | 0x1A0 | 32 | takerAssetProxyMetadata Length |
|
||||
// | | 0x1C0 | ** | takerAssetProxyMetadata Contents |
|
||||
// | | 0x1E0 | 32 | signature Length |
|
||||
// | | 0x200 | ** | signature Contents |
|
||||
// | Data | | 12 * 32 | order: |
|
||||
// | | 0x000 | | 1. senderAddress |
|
||||
// | | 0x020 | | 2. makerAddress |
|
||||
// | | 0x040 | | 3. takerAddress |
|
||||
// | | 0x060 | | 4. feeRecipientAddress |
|
||||
// | | 0x080 | | 5. makerAssetAmount |
|
||||
// | | 0x0A0 | | 6. takerAssetAmount |
|
||||
// | | 0x0C0 | | 7. makerFeeAmount |
|
||||
// | | 0x0E0 | | 8. takerFeeAmount |
|
||||
// | | 0x100 | | 9. expirationTimeSeconds |
|
||||
// | | 0x120 | | 10. salt |
|
||||
// | | 0x140 | | 11. Offset to makerAssetProxyMetadata (*) |
|
||||
// | | 0x160 | | 12. Offset to takerAssetProxyMetadata (*) |
|
||||
// | | 0x180 | 32 | makerAssetProxyMetadata Length |
|
||||
// | | 0x1A0 | ** | makerAssetProxyMetadata Contents |
|
||||
// | | 0x1C0 | 32 | takerAssetProxyMetadata Length |
|
||||
// | | 0x1E0 | ** | takerAssetProxyMetadata Contents |
|
||||
// | | 0x200 | 32 | signature Length |
|
||||
// | | 0x220 | ** | signature Contents |
|
||||
|
||||
// * Offsets are calculated from the beginning of the current area: Header, Params, Data:
|
||||
// An offset stored in the Params area is calculated from the beginning of the Params section.
|
||||
@@ -150,19 +151,20 @@ contract MixinWrapperFunctions is
|
||||
mstore(dataAreaEnd, mload(sourceOffset)) // makerAddress
|
||||
mstore(add(dataAreaEnd, 0x20), mload(add(sourceOffset, 0x20))) // takerAddress
|
||||
mstore(add(dataAreaEnd, 0x40), mload(add(sourceOffset, 0x40))) // feeRecipientAddress
|
||||
mstore(add(dataAreaEnd, 0x60), mload(add(sourceOffset, 0x60))) // makerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0x80), mload(add(sourceOffset, 0x80))) // takerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0xA0), mload(add(sourceOffset, 0xA0))) // makerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0xC0), mload(add(sourceOffset, 0xC0))) // takerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // expirationTimeSeconds
|
||||
mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // salt
|
||||
mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // Offset to makerAssetProxyMetadata
|
||||
mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to takerAssetProxyMetadata
|
||||
dataAreaEnd := add(dataAreaEnd, 0x160)
|
||||
sourceOffset := add(sourceOffset, 0x160)
|
||||
mstore(add(dataAreaEnd, 0x60), mload(add(sourceOffset, 0x60))) // senderAddress
|
||||
mstore(add(dataAreaEnd, 0x80), mload(add(sourceOffset, 0x80))) // makerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0xA0), mload(add(sourceOffset, 0xA0))) // takerAssetAmount
|
||||
mstore(add(dataAreaEnd, 0xC0), mload(add(sourceOffset, 0xC0))) // makerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0xE0), mload(add(sourceOffset, 0xE0))) // takerFeeAmount
|
||||
mstore(add(dataAreaEnd, 0x100), mload(add(sourceOffset, 0x100))) // expirationTimeSeconds
|
||||
mstore(add(dataAreaEnd, 0x120), mload(add(sourceOffset, 0x120))) // salt
|
||||
mstore(add(dataAreaEnd, 0x140), mload(add(sourceOffset, 0x140))) // Offset to makerAssetProxyMetadata
|
||||
mstore(add(dataAreaEnd, 0x160), mload(add(sourceOffset, 0x160))) // Offset to takerAssetProxyMetadata
|
||||
dataAreaEnd := add(dataAreaEnd, 0x180)
|
||||
sourceOffset := add(sourceOffset, 0x180)
|
||||
|
||||
// Write offset to <order.makerAssetProxyMetadata>
|
||||
mstore(add(dataAreaStart, mul(9, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
|
||||
// Calculate length of <order.makerAssetProxyMetadata>
|
||||
arrayLenBytes := mload(sourceOffset)
|
||||
@@ -181,7 +183,7 @@ contract MixinWrapperFunctions is
|
||||
}
|
||||
|
||||
// Write offset to <order.takerAssetProxyMetadata>
|
||||
mstore(add(dataAreaStart, mul(10, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
mstore(add(dataAreaStart, mul(11, 0x20)), sub(dataAreaEnd, dataAreaStart))
|
||||
|
||||
// Calculate length of <order.takerAssetProxyMetadata>
|
||||
arrayLenBytes := mload(sourceOffset)
|
||||
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
Copyright 2018 ZeroEx Intl.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
pragma solidity ^0.4.21;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import "./MSignatureValidator.sol";
|
||||
|
||||
contract MTransactions is MSignatureValidator {
|
||||
|
||||
/// @dev Executes an exchange method call in the context of signer.
|
||||
/// @param salt Arbitrary number to ensure uniqueness of transaction hash.
|
||||
/// @param signer Address of transaction signer.
|
||||
/// @param data AbiV2 encoded calldata.
|
||||
/// @param signature Proof of signer transaction by signer.
|
||||
function executeTransaction(
|
||||
uint256 salt,
|
||||
address signer,
|
||||
bytes data,
|
||||
bytes signature)
|
||||
external;
|
||||
|
||||
function getSignerAddress()
|
||||
internal
|
||||
view
|
||||
returns (address);
|
||||
}
|
Reference in New Issue
Block a user