Skip to content

Commit

Permalink
Fn codec
Browse files Browse the repository at this point in the history
  • Loading branch information
ultrasecreth committed Jul 26, 2023
1 parent 5ac171c commit 13f6471
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/utils/FunctionCodec.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library FunctionCodec {
function encodeParams(address contractAddr, bytes4 selector) internal pure returns (bytes24) {
return bytes24(bytes20(contractAddr)) | bytes24(selector) >> 160;
}

function decodeParams(bytes24 encoded) internal pure returns (address contractAddr, bytes4 selector) {
contractAddr = address(bytes20(encoded));
selector = bytes4(encoded << 160);
}

function encodeFunction(function () external returns(string memory) f) internal pure returns (bytes24) {
return encodeParams(f.address, f.selector);
}

function decodeFunction(
address contractAddr,
bytes4 selector
)
internal
pure
returns (function () external returns(string memory) f)
{
uint32 s = uint32(selector);
assembly {
f.address := contractAddr
f.selector := s
}
}

function decodeFunction(bytes24 encoded) internal pure returns (function () external returns(string memory) f) {
(address contractAddr, bytes4 selector) = decodeParams(encoded);
return decodeFunction(contractAddr, selector);
}
}
44 changes: 44 additions & 0 deletions test/utils/FunctionCodec.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { PRBTest } from "@prb/test/PRBTest.sol";
import { console2 } from "forge-std/console2.sol";
import { StdCheats } from "forge-std/StdCheats.sol";

import "src/utils/FunctionCodec.sol";

contract FunctionCodecTest is PRBTest, StdCheats {
function mockCallback() external pure returns(string memory) {
return "Hello, world!";
}

function testEncodeParams() public {
assertEq(
FunctionCodec.encodeParams(address(this), this.mockCallback.selector),
bytes24(abi.encodePacked(address(this), this.mockCallback.selector))
);
}

function testDecodeParams() public {
bytes24 encoded = FunctionCodec.encodeParams(address(this), this.mockCallback.selector);
(address contractAddr, bytes4 selector) = FunctionCodec.decodeParams(encoded);
assertEq(contractAddr, address(this));
assertEq(selector, this.mockCallback.selector);
}

function testEncodeFunction() public {
bytes24 encoded = FunctionCodec.encodeFunction(this.mockCallback);
assertEq(encoded, bytes24(abi.encodePacked(address(this), this.mockCallback.selector)));
}

function testDecodeFunction() public {
function () external returns(string memory) f = FunctionCodec.decodeFunction(address(this), this.mockCallback.selector);
assertEq(f(), this.mockCallback());
}

function testDecodeFunction2() public {
bytes24 encoded = FunctionCodec.encodeFunction(this.mockCallback);
function () external returns(string memory) f = FunctionCodec.decodeFunction(encoded);
assertEq(f(), this.mockCallback());
}
}

0 comments on commit 13f6471

Please sign in to comment.