Removed receiverData and onReceive
callback from ERC721 proxy.
This commit is contained in:
@@ -83,19 +83,15 @@ contract ERC721Proxy is
|
||||
// WARNING: The ABIv2 specification allows additional padding between
|
||||
// the Params and Data section. This will result in a larger
|
||||
// offset to assetData.
|
||||
|
||||
|
||||
// Asset data itself is encoded as follows:
|
||||
//
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 3 * 32 | function parameters: |
|
||||
// | Params | | 2 * 32 | function parameters: |
|
||||
// | | 4 | 12 + 20 | 1. token address |
|
||||
// | | 36 | | 2. tokenId |
|
||||
// | | 68 | | 3. offset to receiverData (*) |
|
||||
// | Data | | | receiverData: |
|
||||
// | | 100 | 32 | receiverData Length |
|
||||
// | | 132 | ** | receiverData Contents |
|
||||
|
||||
// We construct calldata for the `token.safeTransferFrom` ABI.
|
||||
// The layout of this calldata is in the table below.
|
||||
@@ -103,14 +99,10 @@ contract ERC721Proxy is
|
||||
// | Area | Offset | Length | Contents |
|
||||
// |----------|--------|---------|-------------------------------------|
|
||||
// | Header | 0 | 4 | function selector |
|
||||
// | Params | | 4 * 32 | function parameters: |
|
||||
// | Params | | 3 * 32 | function parameters: |
|
||||
// | | 4 | | 1. from |
|
||||
// | | 36 | | 2. to |
|
||||
// | | 68 | | 3. tokenId |
|
||||
// | | 100 | | 4. offset to receiverData (*) |
|
||||
// | Data | | | receiverData: |
|
||||
// | | 132 | 32 | receiverData Length |
|
||||
// | | 164 | ** | receiverData Contents |
|
||||
|
||||
// There exists only 1 of each token.
|
||||
// require(amount == 1, "INVALID_AMOUNT")
|
||||
@@ -122,76 +114,32 @@ contract ERC721Proxy is
|
||||
mstore(96, 0)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
// Require assetData to be at least 132 bytes
|
||||
let offset := calldataload(4)
|
||||
if lt(calldataload(add(offset, 4)), 132) {
|
||||
// Revert with `Error("LENGTH_GREATER_THAN_131_REQUIRED")`
|
||||
mstore(0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(32, 0x0000002000000000000000000000000000000000000000000000000000000000)
|
||||
mstore(64, 0x000000204c454e4754485f475245415445525f5448414e5f3133315f52455155)
|
||||
mstore(96, 0x4952454400000000000000000000000000000000000000000000000000000000)
|
||||
revert(0, 100)
|
||||
}
|
||||
|
||||
/////// Setup State ///////
|
||||
// `cdStart` is the start of the calldata for
|
||||
// `token.safeTransferFrom` (equal to free memory ptr).
|
||||
let cdStart := mload(64)
|
||||
// `dataAreaLength` is the total number of words
|
||||
// needed to store `receiverData`
|
||||
// As-per the ABI spec, this value is padded up to
|
||||
// the nearest multiple of 32,
|
||||
// and includes 32-bytes for length.
|
||||
// It's calculated as folows:
|
||||
// - Unpadded length in bytes = `mload(receiverData) + 32`
|
||||
// - Add 31 to convert rounding down to rounding up.
|
||||
// Combined with the previous and this is `63`.
|
||||
// - Round down to nearest multiple of 32 by clearing
|
||||
// bits 0x1F. This is done with `and` and a mask.
|
||||
|
||||
/////// Setup Header Area ///////
|
||||
// This area holds the 4-byte `transferFromSelector`.
|
||||
// Any trailing data in transferFromSelector will be
|
||||
// overwritten in the next `mstore` call.
|
||||
mstore(cdStart, 0xb88d4fde00000000000000000000000000000000000000000000000000000000)
|
||||
mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
|
||||
|
||||
/////// Setup Params Area ///////
|
||||
// Each parameter is padded to 32-bytes.
|
||||
// The entire Params Area is 128 bytes.
|
||||
// Notes:
|
||||
// 1. A 20-byte mask is applied to addresses
|
||||
// to zero-out the unused bytes.
|
||||
// 2. The offset to `receiverData` is the length
|
||||
// of the Params Area (128 bytes).
|
||||
|
||||
let length := calldataload(add(offset, 136))
|
||||
let token := calldataload(add(offset, 40))
|
||||
|
||||
// Round length up to multiple of 32
|
||||
length := and(add(length, 31), 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0)
|
||||
|
||||
// Copy `from` and `to`
|
||||
calldatacopy(add(cdStart, 4), 36, 64)
|
||||
|
||||
// TokenId
|
||||
mstore(add(cdStart, 68), calldataload(add(offset, 72)))
|
||||
|
||||
// Offset to receiverData
|
||||
mstore(add(cdStart, 100), 128)
|
||||
|
||||
// receiverData (including length)
|
||||
calldatacopy(add(cdStart, 132), add(offset, 136), add(length, 32))
|
||||
|
||||
/////// Call `token.safeTransferFrom` using the calldata ///////
|
||||
// We copy the fields `from` and `to` in bulk
|
||||
// from our own calldata to the new calldata.
|
||||
calldatacopy(4, 36, 64)
|
||||
|
||||
// Copy `tokenId` field from our own calldata to the new calldata.
|
||||
let assetDataOffset := calldataload(4)
|
||||
calldatacopy(68, add(assetDataOffset, 72), 32)
|
||||
|
||||
/////// Call `token.transferFrom` using the calldata ///////
|
||||
let token := calldataload(add(assetDataOffset, 40))
|
||||
let success := call(
|
||||
gas, // forward all gas
|
||||
token, // call address of token contract
|
||||
0, // don't send any ETH
|
||||
cdStart, // pointer to start of input
|
||||
add(length, 164), // length of input
|
||||
0, // write output to null
|
||||
0 // output size is 0 bytes
|
||||
gas, // forward all gas
|
||||
token, // call address of token contract
|
||||
0, // don't send any ETH
|
||||
0, // pointer to start of input
|
||||
100, // length of input
|
||||
0, // write output to null
|
||||
0 // output size is 0 bytes
|
||||
)
|
||||
if success {
|
||||
return(0, 0)
|
||||
|
Reference in New Issue
Block a user