Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

limit order metatransactions #44

Merged
merged 9 commits into from
Nov 24, 2020
Merged

limit order metatransactions #44

merged 9 commits into from
Nov 24, 2020

Conversation

smarx
Copy link
Contributor

@smarx smarx commented Nov 23, 2020

Description

This adds support for metatransactions that invoke fillLimitOrder and fillRfqOrder.

Testing instructions

yarn test

Types of changes

  • New feature

Checklist:

  • Prefix PR title with [WIP] if necessary.
  • Add tests to cover changes as needed.
  • Update documentation as needed.
  • Add new entries to the relevant CHANGELOG.jsons.

Copy link
Contributor

@hysz hysz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good! A few questions about optimizations. As well, let me confirm that we only need MTX's on the fill and not fillOrKill.

bytes memory args = new bytes(data.length - 4);
uint256 from;
uint256 to;
assembly {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are no dynamic fields, I wonder if we could easily get away with just copying fields from the calldata directly into the structs. Ex,

// makerToken
mstore(order, mload(add(data, 0x24)))
// takerToken
mstore(add(order, 0x20), mload(add(data, 0x44)))
// makerAmount
mstore(add(order, 0x40), mload(add(data, 0x64)))
...

mstore(signature, ...)
...

takerTokenFillAmount := mload(add(data, ...)))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can do that, but I'm not convinced it's going to be (much) better. We're already doing a low-level memory copy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I was thinking this could save us the abi.decode, which looking in Remix is ~4000 gas . Alternatively we could probably also just use memCpy to extract the order/signature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually given the time constraints I'm down to punt on optimizations for now. We can do more golfing in 4.1.


return _callSelf(
state.hash,
abi.encodeWithSelector(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually... I wonder if if we could just modify in-place the mtx.state.callData. This is untested, but something like:

assembly {
    // length on input calldata
    let mtxCallDataLen := mload(data)

    // we'll extend the input calldata with two extra fields (0x40)
    mstore(data, add(mtxCallDataLen, 0x40)) 

    // where in memory to append these fields (right after state.mtx.callData)
    let mtxCallDataEnd := add(data, add(0x20, mul(mtxCallDataLen, 0x20))) 

    // add fields to end of state.mtx.callData
    mstore(mtxCallDataEnd, taker)
    mstore(add(mtxCallDataEnd, 0x20), sender)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^^ we'd also have to replace the selector w/ INativeOrdersFeature._fillLimitOrder.selector

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC, this is a bit dangerous. We'd be writing to memory that may not be safe to touch. How important is gas efficiency here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we do control the struct, so we can make sure we have room to overwrite things. But I think we still need to decide how important gas efficiency is before we do that sort of thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah... I was thinking we could probably show it's safe so long as we don't add code after executing the MTX. But, looking more thoroughly, I see we could also be running in a batchExecute in which case it's probably pretty likely we're overwriting someone else's memory.

Copy link
Contributor

@hysz hysz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! (~‾▿‾)~

@smarx smarx changed the title Feat/mtx limit order limit order metatransactions Nov 24, 2020
Copy link
Contributor

@dorothy-zbornak dorothy-zbornak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. I'm not worried about optimizing this right now. We can wait to see if tokenlon has issues with it first.

Comment on lines 510 to 518
bytes memory data = state.mtx.callData;
bytes memory args = new bytes(data.length - 4);
uint256 from;
uint256 to;
assembly {
from := add(data, 36) // skip length and selector
to := add(args, 32) // after length
}
LibBytesV06.memCopy(to, from, data.length - 4);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we refactor this out into a stripSelectorFromCallData() function or something?

@@ -319,6 +319,7 @@ contract NativeOrdersFeature is
address sender
)
public
virtual
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really hate this keyword.

bytes32 greedyTokensBloomFilter
)
public
NativeOrdersFeature(zeroExAddress, weth, staking, protocolFeeMultiplier, greedyTokensBloomFilter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably just populate all these with nulls here to reduce setup in the test script.

@smarx smarx merged commit e2ee341 into development Nov 24, 2020
@smarx smarx deleted the feat/mtx-limit-order branch November 24, 2020 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants