Skip to content
This repository has been archived by the owner on Jul 9, 2021. It is now read-only.

Implement StaticCallProxy #1863

Merged
merged 16 commits into from
Jun 21, 2019
Merged

Conversation

abandeali1
Copy link
Member

@abandeali1 abandeali1 commented Jun 10, 2019

Description

  • Implements ZEIP-39
  • Adds support to types and order-utils
  • Updates abi-gen-templates to include getABIEncodedTransactionData in the callAsync template (rather than the tx template). This was useful for implementing tests for the StaticCallProxy.
  • Includes a more descriptive revert reason in the ERC1155Proxy (also used in the StaticCallProxy)
  • Adds StaticCallProxy support to LibAssetData

Testing instructions

Types of changes

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.

@coveralls
Copy link

coveralls commented Jun 10, 2019

Coverage Status

Coverage decreased (-0.1%) to 83.287% when pulling 323fb0a on feat/contracts/static-call-proxy into fc25752 on development.

@abandeali1 abandeali1 force-pushed the feat/contracts/static-call-proxy branch from 4164577 to 6342faa Compare June 10, 2019 16:29
// + 32 (assetData len)
// + 4 (proxyId)
// + 32 (callTarget)
// + 32 (assetDataOffset)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be + 32 (staticCallDataOffset) instead of + 32 (assetDataOffset)

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 ~ I'm excited for this functionality 💪 ! Just left a few small notes.

pure
{}

function dynamicInputFunction(bytes calldata a)
Copy link
Contributor

Choose a reason for hiding this comment

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

It could be good to do some sanity check on the input data, to ensure it was forwarded correctly.

return isOdd;
}

function noInputFunction()
Copy link
Contributor

Choose a reason for hiding this comment

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

It could be good to do a sanity check to ensure that calldata() == <selector> without any extra data.

(bool success,) = _STATIC_CALL_PROXY_ADDRESS.staticcall(transferFromData);

// Success means that the staticcall can be made an unlimited amount of times
balance = success ? _MAX_UINT256 : 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be worthwhile to special-case Multi-Asset Data, especially in this case where the only valid values are MAX_UINT256 and 0. The alternative would be to highlight in our documentation that any non-zero value implies an unlimited amount of times, in which case we should add a note to the function comment + add a test case for this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm also not sure exactly how to interpret "the staticcall can be made an unlimited amount of times". What if the following function is called:

function a() public view {
  require(block.number < 7977075);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

That call can be made an unlimited amount of times at the particular block in which this gets called (not accounting for gas). This should always be true since the staticcall can't update state and will therefore never have side effects that would prevent the staticcall from failing if called again.

// | | 4 | | 1. offset to assetData (*) |
// | | 36 | | 2. from |
// | | 68 | | 3. to |
// | | 100 | | 4. amount |
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we're moving towards localizing validation within the proxies, we may want to assert that amount is some fixed, standardized value -- like 0. Ex, in the MultiAssetProxy scaling this value should have no effect.

Copy link
Member Author

Choose a reason for hiding this comment

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

The problem is that the Exchange contract doesn't allow 0 transfers. Any non-zero number would be scaled with the MAP.

@abandeali1 abandeali1 force-pushed the feat/contracts/static-call-proxy branch from 6342faa to 5da88f7 Compare June 17, 2019 19:24
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.

Really nice!


// Validate length of `assetData`
let assetDataLen := calldataload(assetDataOffset)
if or(lt(assetDataLen, 100), mod(sub(assetDataLen, 4), 32)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if or(lt(assetDataLen, 100), mod(sub(assetDataLen, 4), 32)) {
if lt(assetDataLen, 132) {
  • staticCallData Length should always be part of the asset data regardless, no?
  • Do we need to enforce that the entire asset data be word-aligned? It's conceivable to me that an abi-encoder (though probably not ours) would not word-align parameters such as bytes types.

Copy link
Member Author

Choose a reason for hiding this comment

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

bytes, of length k (which is assumed to be of type uint256):

enc(X) = enc(k) pad_right(X), i.e. the number of bytes is encoded as a uint256 followed by the actual value of X as a byte sequence, followed by the minimum number of zero-bytes such that len(enc(X)) is a multiple of 32.

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting. I guess this also explains why we word align revert strings.

}),
constants.AWAIT_TRANSACTION_MINED_MS,
);
await erc20Proxy.addAuthorizedAddress.awaitTransactionSuccessAsync(exchange.address, { from: owner });
Copy link
Contributor

Choose a reason for hiding this comment

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

🙏

@abandeali1 abandeali1 requested a review from albrow as a code owner June 18, 2019 04:50
@abandeali1 abandeali1 force-pushed the feat/contracts/static-call-proxy branch from 47c84dd to 8897dc1 Compare June 18, 2019 05:32
@abandeali1 abandeali1 requested a review from feuGeneA as a code owner June 18, 2019 05:32
@abandeali1 abandeali1 force-pushed the feat/contracts/static-call-proxy branch from 8897dc1 to 323fb0a Compare June 19, 2019 02:53
@abandeali1 abandeali1 merged commit 82f7308 into development Jun 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants