Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
feature: Reject taker addresses that are nonzero and not on the white…
Browse files Browse the repository at this point in the history
…list (#896)

* Reject taker addresses that are nonzero and not on the whitelist

* Addressed review feedback
  • Loading branch information
jalextowle authored Aug 8, 2020
1 parent 106b5df commit c7fb4d7
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 61 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

This changelog is a work in progress and may contain notes for versions which have not actually been released. Check the [Releases](https://github.com/0xProject/0x-mesh/releases) page to see full release notes and more information about the latest released versions.

## v9.5.0
## v10.0.0

### Features ✅

- Upgraded to Go 1.14, which contains several WebAssembly performance improvements [#815](https://github.com/0xProject/0x-mesh/pull/815).
- Reject orders that have taker addresses that are non-zero and are not whitelisted. [#896](https://github.com/0xProject/0x-mesh/pull/896).

## v9.4.1

Expand Down
127 changes: 67 additions & 60 deletions ethereum/contract_addresses.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import (

// ContractAddresses maps a contract's name to it's Ethereum address
type ContractAddresses struct {
ERC20Proxy common.Address `json:"erc20Proxy"`
ERC721Proxy common.Address `json:"erc721Proxy"`
ERC1155Proxy common.Address `json:"erc1155Proxy"`
Exchange common.Address `json:"exchange"`
DevUtils common.Address `json:"devUtils"`
WETH9 common.Address `json:"weth9"`
ZRXToken common.Address `json:"zrxToken"`
ChaiBridge common.Address `json:"chaiBridge"`
ChaiToken common.Address `json:"chaiToken"`
MaximumGasPrice common.Address `json:"maximumGasPrice"`
ERC20Proxy common.Address `json:"erc20Proxy"`
ERC721Proxy common.Address `json:"erc721Proxy"`
ERC1155Proxy common.Address `json:"erc1155Proxy"`
Exchange common.Address `json:"exchange"`
// TODO(jalextowle): This should be removed when 0x v4 is released.
ExchangeProxyFlashWallet common.Address `json:"exchangeProxyFlashWallet"`
DevUtils common.Address `json:"devUtils"`
WETH9 common.Address `json:"weth9"`
ZRXToken common.Address `json:"zrxToken"`
ChaiBridge common.Address `json:"chaiBridge"`
ChaiToken common.Address `json:"chaiToken"`
MaximumGasPrice common.Address `json:"maximumGasPrice"`
}

// GanacheAddresses The addresses that the 0x contracts were deployed to on the Ganache snapshot (chainID = 1337).
Expand All @@ -29,55 +31,59 @@ func NewContractAddressesForChainID(chainID int) (ContractAddresses, error) {
switch chainID {
case 1:
return ContractAddresses{
ERC20Proxy: common.HexToAddress("0x95e6f48254609a6ee006f7d493c8e5fb97094cef"),
ERC721Proxy: common.HexToAddress("0xefc70a1b18c432bdc64b596838b4d138f6bc6cad"),
Exchange: common.HexToAddress("0x61935cbdd02287b511119ddb11aeb42f1593b7ef"),
ERC1155Proxy: common.HexToAddress("0x7eefbd48fd63d441ec7435d024ec7c5131019add"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"),
ZRXToken: common.HexToAddress("0xe41d2489571d322189246dafa5ebde1f4699f498"),
ChaiBridge: common.HexToAddress("0x77c31eba23043b9a72d13470f3a3a311344d7438"),
ChaiToken: common.HexToAddress("0x06af07097c9eeb7fd685c692751d5c66db49c215"),
MaximumGasPrice: common.HexToAddress("0xe2bfd35306495d11e3c9db0d8de390cda24563cf"),
ERC20Proxy: common.HexToAddress("0x95e6f48254609a6ee006f7d493c8e5fb97094cef"),
ERC721Proxy: common.HexToAddress("0xefc70a1b18c432bdc64b596838b4d138f6bc6cad"),
ERC1155Proxy: common.HexToAddress("0x7eefbd48fd63d441ec7435d024ec7c5131019add"),
Exchange: common.HexToAddress("0x61935cbdd02287b511119ddb11aeb42f1593b7ef"),
ExchangeProxyFlashWallet: common.HexToAddress("0x22f9dcf4647084d6c31b2765f6910cd85c178c18"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"),
ZRXToken: common.HexToAddress("0xe41d2489571d322189246dafa5ebde1f4699f498"),
ChaiBridge: common.HexToAddress("0x77c31eba23043b9a72d13470f3a3a311344d7438"),
ChaiToken: common.HexToAddress("0x06af07097c9eeb7fd685c692751d5c66db49c215"),
MaximumGasPrice: common.HexToAddress("0xe2bfd35306495d11e3c9db0d8de390cda24563cf"),
}, nil
case 3:
return ContractAddresses{
ERC20Proxy: common.HexToAddress("0xb1408f4c245a23c31b98d2c626777d4c0d766caa"),
ERC721Proxy: common.HexToAddress("0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4"),
Exchange: common.HexToAddress("0xfb2dd2a1366de37f7241c83d47da58fd503e2c64"),
ERC1155Proxy: common.HexToAddress("0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
ZRXToken: common.HexToAddress("0xff67881f8d12f372d91baae9752eb3631ff0ed00"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x407b4128e9ecad8769b2332312a9f655cb9f5f3a"),
ERC20Proxy: common.HexToAddress("0xb1408f4c245a23c31b98d2c626777d4c0d766caa"),
ERC721Proxy: common.HexToAddress("0xe654aac058bfbf9f83fcaee7793311dd82f6ddb4"),
ERC1155Proxy: common.HexToAddress("0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d"),
Exchange: common.HexToAddress("0xfb2dd2a1366de37f7241c83d47da58fd503e2c64"),
ExchangeProxyFlashWallet: common.HexToAddress("0x22f9dcf4647084d6c31b2765f6910cd85c178c18"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
ZRXToken: common.HexToAddress("0xff67881f8d12f372d91baae9752eb3631ff0ed00"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x407b4128e9ecad8769b2332312a9f655cb9f5f3a"),
}, nil
case 4:
return ContractAddresses{
ERC20Proxy: common.HexToAddress("0x2f5ae4f6106e89b4147651688a92256885c5f410"),
ERC721Proxy: common.HexToAddress("0x7656d773e11ff7383a14dcf09a9c50990481cd10"),
ERC1155Proxy: common.HexToAddress("0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d"),
Exchange: common.HexToAddress("0x198805e9682fceec29413059b68550f92868c129"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
ZRXToken: common.HexToAddress("0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x47697b44bd89051e93b4d5857ba8e024800a74ac"),
ERC20Proxy: common.HexToAddress("0x2f5ae4f6106e89b4147651688a92256885c5f410"),
ERC721Proxy: common.HexToAddress("0x7656d773e11ff7383a14dcf09a9c50990481cd10"),
ERC1155Proxy: common.HexToAddress("0x19bb6caa3bc34d39e5a23cedfa3e6c7e7f3c931d"),
Exchange: common.HexToAddress("0x198805e9682fceec29413059b68550f92868c129"),
ExchangeProxyFlashWallet: common.HexToAddress("0x22f9dcf4647084d6c31b2765f6910cd85c178c18"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xc778417e063141139fce010982780140aa0cd5ab"),
ZRXToken: common.HexToAddress("0x8080c7e4b81ecf23aa6f877cfbfd9b0c228c6ffa"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x47697b44bd89051e93b4d5857ba8e024800a74ac"),
}, nil
case 42:
return ContractAddresses{
ERC20Proxy: common.HexToAddress("0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e"),
ERC721Proxy: common.HexToAddress("0x2a9127c745688a165106c11cd4d647d2220af821"),
Exchange: common.HexToAddress("0x4eacd0af335451709e1e7b570b8ea68edec8bc97"),
ERC1155Proxy: common.HexToAddress("0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xd0a1e359811322d97991e03f863a0c30c2cf029c"),
ZRXToken: common.HexToAddress("0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x67a094cf028221ffdd93fc658f963151d05e2a74"),
ERC20Proxy: common.HexToAddress("0xf1ec01d6236d3cd881a0bf0130ea25fe4234003e"),
ERC721Proxy: common.HexToAddress("0x2a9127c745688a165106c11cd4d647d2220af821"),
ERC1155Proxy: common.HexToAddress("0x64517fa2b480ba3678a2a3c0cf08ef7fd4fad36f"),
Exchange: common.HexToAddress("0x4eacd0af335451709e1e7b570b8ea68edec8bc97"),
ExchangeProxyFlashWallet: common.HexToAddress("0x22f9dcf4647084d6c31b2765f6910cd85c178c18"),
DevUtils: common.HexToAddress("0xb1a3d901bad1df7d710fc8d008db7cdd6bbbffe6"),
WETH9: common.HexToAddress("0xd0a1e359811322d97991e03f863a0c30c2cf029c"),
ZRXToken: common.HexToAddress("0x2002d3812f58e35f0ea1ffbf80a75a38c32175fa"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x67a094cf028221ffdd93fc658f963151d05e2a74"),
}, nil
case 1337:
return ganacheAddresses(), nil
Expand Down Expand Up @@ -112,15 +118,16 @@ func ValidateContractAddressesForChainID(chainID int, addresses ContractAddresse
// function allows these addresses to only be defined in one place.
func ganacheAddresses() ContractAddresses {
return ContractAddresses{
ERC20Proxy: common.HexToAddress("0x1dc4c1cefef38a777b15aa20260a54e584b16c48"),
ERC721Proxy: common.HexToAddress("0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"),
ERC1155Proxy: common.HexToAddress("0x6a4a62e5a7ed13c361b176a5f62c2ee620ac0df8"),
Exchange: common.HexToAddress("0x48bacb9266a570d521063ef5dd96e61686dbe788"),
DevUtils: common.HexToAddress("0xb23672f74749bf7916ba6827c64111a4d6de7f11"),
WETH9: common.HexToAddress("0x0b1ba0af832d7c05fd64161e0db78e85978e8082"),
ZRXToken: common.HexToAddress("0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x2c530e4ecc573f11bd72cf5fdf580d134d25f15f"),
ERC20Proxy: common.HexToAddress("0x1dc4c1cefef38a777b15aa20260a54e584b16c48"),
ERC721Proxy: common.HexToAddress("0x1d7022f5b17d2f8b695918fb48fa1089c9f85401"),
ERC1155Proxy: common.HexToAddress("0x6a4a62e5a7ed13c361b176a5f62c2ee620ac0df8"),
Exchange: common.HexToAddress("0x48bacb9266a570d521063ef5dd96e61686dbe788"),
ExchangeProxyFlashWallet: common.HexToAddress("0x22f9dcf4647084d6c31b2765f6910cd85c178c18"),
DevUtils: common.HexToAddress("0xb23672f74749bf7916ba6827c64111a4d6de7f11"),
WETH9: common.HexToAddress("0x0b1ba0af832d7c05fd64161e0db78e85978e8082"),
ZRXToken: common.HexToAddress("0x871dd7c2b4b25e1aa18728e9d5f2af4c4e431f5c"),
ChaiBridge: common.HexToAddress("0x0000000000000000000000000000000000000000"),
ChaiToken: common.HexToAddress("0x0000000000000000000000000000000000000000"),
MaximumGasPrice: common.HexToAddress("0x2c530e4ecc573f11bd72cf5fdf580d134d25f15f"),
}
}
7 changes: 7 additions & 0 deletions scenario/orderopts/orderopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ func SenderAddress(address common.Address) Option {
}
}

func TakerAddress(address common.Address) Option {
return func(cfg *Config) error {
cfg.Order.TakerAddress = address
return nil
}
}

func FeeRecipientAddress(address common.Address) Option {
return func(cfg *Config) error {
cfg.Order.FeeRecipientAddress = address
Expand Down
4 changes: 4 additions & 0 deletions zeroex/ordervalidator/order_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,10 @@ var (
Code: "DatabaseFullOfOrders",
Message: "database is full of pinned orders and no orders can be deleted to make space (consider increasing MAX_ORDERS_IN_STORAGE)",
}
ROTakerAddressNotAllowed = RejectedOrderStatus{
Code: "TakerAddressNotAllowed",
Message: "the taker address is not a whitelisted address",
}
)

// ROInvalidSchemaCode is the RejectedOrderStatus emitted if an order doesn't conform to the order schema
Expand Down
17 changes: 17 additions & 0 deletions zeroex/orderwatch/order_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,23 @@ func (w *Watcher) meshSpecificOrderValidation(orders []*zeroex.SignedOrder, chai
})
continue
}
// NOTE(jalextowle): Orders with a taker address are only accessible to
// one taker, which complicates more sophisticated pruning technology.
// With this in mind, we only allow whitelisted taker addresses to be
// propogated throughout the network. This whitelist should only include
// addresses that correspond to contracts allow anyone to fill these
// orders.
// TODO(jalextowle): If any other addresses are whitelisted, create
// a isTakerAddressWhitelisted function.
if order.TakerAddress != constants.NullAddress && order.TakerAddress != w.contractAddresses.ExchangeProxyFlashWallet {
results.Rejected = append(results.Rejected, &ordervalidator.RejectedOrderInfo{
OrderHash: orderHash,
SignedOrder: order,
Kind: ordervalidator.MeshValidation,
Status: ordervalidator.ROTakerAddressNotAllowed,
})
continue
}
if order.ChainID.Cmp(big.NewInt(int64(chainID))) != 0 {
results.Rejected = append(results.Rejected, &ordervalidator.RejectedOrderInfo{
OrderHash: orderHash,
Expand Down
62 changes: 62 additions & 0 deletions zeroex/orderwatch/order_watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,68 @@ func init() {
}
}

func TestOrderWatcherTakerWhitelist(t *testing.T) {
teardownSubTest := setupSubTest(t)
defer teardownSubTest(t)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
database, err := db.New(ctx, db.TestOptions())
require.NoError(t, err)

blockWatcher, orderWatcher := setupOrderWatcher(ctx, t, ethRPCClient, database)
require.NoError(t, err)

testCases := []*struct {
order *zeroex.SignedOrder
isTakerAddressWhitelisted bool
}{
{
scenario.NewSignedTestOrder(t, orderopts.SetupMakerState(true)),
true,
},
{
scenario.NewSignedTestOrder(
t,
orderopts.SetupMakerState(true),
orderopts.TakerAddress(ganacheAddresses.ExchangeProxyFlashWallet),
),
true,
},
{
scenario.NewSignedTestOrder(
t,
orderopts.SetupMakerState(true),
orderopts.TakerAddress(common.HexToAddress("0x1")),
),
false,
},
}

err = blockWatcher.SyncToLatestBlock()
require.NoError(t, err)

for _, testCase := range testCases {
results, err := orderWatcher.ValidateAndStoreValidOrders(ctx, []*zeroex.SignedOrder{testCase.order}, false, constants.TestChainID)
require.NoError(t, err)
if testCase.isTakerAddressWhitelisted {
orderHash, err := testCase.order.ComputeOrderHash()
require.NoError(t, err)
assert.Len(t, results.Rejected, 0)
require.Len(t, results.Accepted, 1)
assert.Equal(t, results.Accepted[0].OrderHash, orderHash)
} else {
orderHash, err := testCase.order.ComputeOrderHash()
require.NoError(t, err)
assert.Len(t, results.Accepted, 0)
require.Len(t, results.Rejected, 1)
assert.Equal(t, results.Rejected[0].OrderHash, orderHash)
assert.Equal(t, results.Rejected[0].Kind, ordervalidator.MeshValidation)
assert.Equal(t, results.Rejected[0].Status, ordervalidator.ROTakerAddressNotAllowed)
}
}
}

func TestOrderWatcherStoresValidOrders(t *testing.T) {
if !serialTestsEnabled {
t.Skip("Serial tests (tests which cannot run in parallel) are disabled. You can enable them with the --serial flag")
Expand Down

0 comments on commit c7fb4d7

Please sign in to comment.