Last active
May 28, 2020 15:17
-
-
Save k06a/097dcac25d33aea6cacc94752a415cb2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function compressCall(encodedCall) { | |
let zippedBytes = '0x'; | |
for (let i = 2; i < encodedCall.length; i += 2) { | |
let length = 1; | |
if (encodedCall[i] === '0' && encodedCall[i + 1] == '0') { | |
while ( | |
length < 127 && | |
i + length*2 < encodedCall.length && | |
encodedCall[i + length*2] === '0' && encodedCall[i + length*2 + 1] === '0') | |
{ | |
length += 1; | |
} | |
zippedBytes += (length + 128).toString(16).padStart(2, '0'); | |
i += (length - 1) * 2; | |
} | |
else { | |
while ( | |
length < 127 && | |
i + length*2 < encodedCall.length && | |
(encodedCall[i + length*2] !== '0' || encodedCall[i + length*2 + 1] !== '0')) | |
{ | |
length += 1; | |
} | |
zippedBytes += length.toString(16).padStart(2, '0') + encodedCall.substr(i, length * 2); | |
i += (length - 1) * 2; | |
} | |
} | |
return zippedBytes; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.0; | |
contract CompressedCaller { | |
function compressedCall( | |
address target, | |
uint256 totalLength, | |
bytes memory zipped | |
) | |
public | |
payable | |
returns (bytes memory result) | |
{ | |
(bytes memory data, uint decompressedLength) = decompress(totalLength, zipped); | |
require(decompressedLength == totalLength, "Uncompress error"); | |
bool success; | |
(success, result) = target.call.value(msg.value)(data); | |
require(success, "Decompressed call failed"); | |
} | |
function decompress( | |
uint256 totalLength, | |
bytes memory zipped | |
) | |
public | |
pure | |
returns ( | |
bytes memory data, | |
uint256 index | |
) | |
{ | |
data = new bytes(totalLength); | |
for (uint i = 0; i < zipped.length; i++) { | |
uint len = uint(uint8(zipped[i]) & 0x7F); | |
if ((zipped[i] & 0x80) == 0) { | |
memcpy(data, index, zipped, i + 1, len); | |
i += len; | |
} | |
index += len; | |
} | |
} | |
// | |
// Modified version of: | |
// https://github.com/Arachnid/solidity-stringutils/blob/master/src/strings.sol#L45 | |
// | |
function memcpy( | |
bytes memory destMem, | |
uint dest, | |
bytes memory srcMem, | |
uint src, | |
uint len | |
) | |
private | |
pure | |
{ | |
uint mask = 256 ** (32 - len % 32) - 1; | |
assembly { | |
dest := add(add(destMem, 32), dest) | |
src := add(add(srcMem, 32), src) | |
// Copy word-length chunks while possible | |
for { } gt(len, 31) { len := sub(len, 32) } { // (!<) is the same as (>=) | |
mstore(dest, mload(src)) | |
dest := add(dest, 32) | |
src := add(src, 32) | |
} | |
// Copy remaining bytes | |
let srcPart := and(mload(src), not(mask)) | |
let destPart := and(mload(dest), mask) | |
mstore(dest, or(destPart, srcPart)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment