Skip to content

Commit 01748e9

Browse files
committed
enhancement/precompile-resolveaddress
1 parent d3f5f97 commit 01748e9

File tree

5 files changed

+136
-3
lines changed

5 files changed

+136
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Additional FVM support can be found in the [filecoin-solidity library](https://g
6767
| Supported | Name | Address |
6868
| :-------: | :--- | :------ |
6969
|| ResolveAddress | `0xfe00000000000000000000000000000000000001` |
70-
| | LookupDelegatedAddress | `0xfe00000000000000000000000000000000000002` |
70+
| | LookupDelegatedAddress | `0xfe00000000000000000000000000000000000002` |
7171
|| CallActorByAddress | `0xfe00000000000000000000000000000000000003` |
7272
|| CallActorById | `0xfe00000000000000000000000000000000000005` |
7373
|| GetBeaconRandomness | `0xfe00000000000000000000000000000000000006` |

src/FVMAddress.sol

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
pragma solidity ^0.8.30;
3+
4+
import {LOOKUP_DELEGATED_ADDRESS} from "./FVMPrecompiles.sol";
5+
6+
library FVMAddress {
7+
function lookupDelegatedAddress(uint64 actorId) internal view returns (bool success, bytes memory delegatedAddress) {
8+
(success, delegatedAddress) = address(LOOKUP_DELEGATED_ADDRESS).staticcall(abi.encode(uint256(actorId)));
9+
}
10+
11+
function actorIdToEthAddress(uint64 actorId) internal view returns (bool success, address ethAddress) {
12+
bytes memory delegatedAddress;
13+
(success, delegatedAddress) = lookupDelegatedAddress(actorId);
14+
15+
if (success && delegatedAddress.length == 22) {
16+
if (delegatedAddress[0] == 0x04 && delegatedAddress[1] == 0x0a) {
17+
assembly ("memory-safe") {
18+
ethAddress := mload(add(delegatedAddress, 22))
19+
}
20+
return (true, ethAddress);
21+
}
22+
}
23+
return (false, address(0));
24+
}
25+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
pragma solidity ^0.8.30;
3+
4+
contract FVMLookupDelegatedAddress {
5+
mapping(uint64 => bytes) public delegatedAddressMocks;
6+
7+
function mockLookupDelegatedAddress(uint64 actorId, bytes memory delegatedAddress) external {
8+
delegatedAddressMocks[actorId] = delegatedAddress;
9+
}
10+
11+
function mockActorIdToEthAddress(uint64 actorId, address ethAddress) external {
12+
bytes memory delegatedAddress = new bytes(22);
13+
delegatedAddress[0] = 0x04;
14+
delegatedAddress[1] = 0x0a;
15+
16+
for (uint256 i = 0; i < 20; i++) {
17+
delegatedAddress[i + 2] = bytes20(ethAddress)[i];
18+
}
19+
20+
delegatedAddressMocks[actorId] = delegatedAddress;
21+
}
22+
23+
fallback() external {
24+
uint64 actorId;
25+
assembly ("memory-safe") {
26+
actorId := calldataload(0)
27+
}
28+
29+
bytes memory delegatedAddress = delegatedAddressMocks[actorId];
30+
31+
assembly ("memory-safe") {
32+
let len := mload(delegatedAddress)
33+
if len {
34+
return(add(delegatedAddress, 32), len)
35+
}
36+
return(0, 0)
37+
}
38+
}
39+
}

src/mocks/MockFVMTest.sol

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,20 @@ pragma solidity ^0.8.30;
33

44
import {Test} from "forge-std/Test.sol";
55

6-
import {CALL_ACTOR_BY_ADDRESS, CALL_ACTOR_BY_ID, GET_BEACON_RANDOMNESS} from "../FVMPrecompiles.sol";
6+
import {CALL_ACTOR_BY_ADDRESS, CALL_ACTOR_BY_ID, GET_BEACON_RANDOMNESS, LOOKUP_DELEGATED_ADDRESS} from "../FVMPrecompiles.sol";
77
import {FVMCallActorByAddress} from "./FVMCallActorByAddress.sol";
88
import {FVMCallActorById} from "./FVMCallActorById.sol";
99
import {FVMGetBeaconRandomness} from "./FVMGetBeaconRandomness.sol";
10+
import {FVMLookupDelegatedAddress} from "./FVMLookupDelegatedAddress.sol";
1011

11-
/// @notice Mocks the FVM precompiles for forge test
1212
contract MockFVMTest is Test {
1313
FVMGetBeaconRandomness public constant RANDOMNESS_PRECOMPILE = FVMGetBeaconRandomness(GET_BEACON_RANDOMNESS);
14+
FVMLookupDelegatedAddress public constant LOOKUP_DELEGATED_ADDRESS_PRECOMPILE = FVMLookupDelegatedAddress(LOOKUP_DELEGATED_ADDRESS);
1415

1516
function setUp() public virtual {
1617
vm.etch(CALL_ACTOR_BY_ADDRESS, address(new FVMCallActorByAddress()).code);
1718
vm.etch(CALL_ACTOR_BY_ID, address(new FVMCallActorById()).code);
1819
vm.etch(GET_BEACON_RANDOMNESS, address(new FVMGetBeaconRandomness()).code);
20+
vm.etch(LOOKUP_DELEGATED_ADDRESS, address(new FVMLookupDelegatedAddress()).code);
1921
}
2022
}

test/Address.t.sol

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// SPDX-License-Identifier: Apache-2.0 OR MIT
2+
pragma solidity ^0.8.30;
3+
4+
import {MockFVMTest} from "../src/mocks/MockFVMTest.sol";
5+
import {FVMAddress} from "../src/FVMAddress.sol";
6+
7+
contract AddressTest is MockFVMTest {
8+
using FVMAddress for uint64;
9+
10+
function testLookupDelegatedAddressNotFound() public view {
11+
uint64 fakeActorId = 99999;
12+
(bool success, bytes memory delegatedAddress) = FVMAddress.lookupDelegatedAddress(fakeActorId);
13+
assertTrue(success);
14+
assertEq(delegatedAddress.length, 0);
15+
}
16+
17+
function testLookupDelegatedAddressMocked() public {
18+
uint64 testActorId = 54321;
19+
bytes memory expectedAddress = hex"040a1234567890abcdef1234567890abcdef1234";
20+
21+
LOOKUP_DELEGATED_ADDRESS_PRECOMPILE.mockLookupDelegatedAddress(testActorId, expectedAddress);
22+
23+
(bool success, bytes memory delegatedAddress) = FVMAddress.lookupDelegatedAddress(testActorId);
24+
assertTrue(success);
25+
assertEq(delegatedAddress, expectedAddress);
26+
}
27+
28+
function testActorIdToEthAddress() public {
29+
uint64 testActorId = 11111;
30+
address expectedEthAddress = address(0x1234567890AbcdEF1234567890aBcdef12345678);
31+
32+
LOOKUP_DELEGATED_ADDRESS_PRECOMPILE.mockActorIdToEthAddress(testActorId, expectedEthAddress);
33+
34+
(bool success, address ethAddress) = FVMAddress.actorIdToEthAddress(testActorId);
35+
assertTrue(success);
36+
assertEq(ethAddress, expectedEthAddress);
37+
}
38+
39+
function testActorIdToEthAddressNotFound() public view {
40+
uint64 fakeActorId = 99999;
41+
(bool success, address ethAddress) = FVMAddress.actorIdToEthAddress(fakeActorId);
42+
assertFalse(success);
43+
assertEq(ethAddress, address(0));
44+
}
45+
46+
function testActorIdToEthAddressInvalidPrefix() public {
47+
uint64 testActorId = 22222;
48+
bytes memory invalidAddress = hex"ff0a1234567890abcdef1234567890abcdef1234";
49+
50+
LOOKUP_DELEGATED_ADDRESS_PRECOMPILE.mockLookupDelegatedAddress(testActorId, invalidAddress);
51+
52+
(bool success, address ethAddress) = FVMAddress.actorIdToEthAddress(testActorId);
53+
assertFalse(success);
54+
assertEq(ethAddress, address(0));
55+
}
56+
57+
function testActorIdToEthAddressWrongLength() public {
58+
uint64 testActorId = 33333;
59+
bytes memory shortAddress = hex"040a12345678";
60+
61+
LOOKUP_DELEGATED_ADDRESS_PRECOMPILE.mockLookupDelegatedAddress(testActorId, shortAddress);
62+
63+
(bool success, address ethAddress) = FVMAddress.actorIdToEthAddress(testActorId);
64+
assertFalse(success);
65+
assertEq(ethAddress, address(0));
66+
}
67+
}

0 commit comments

Comments
 (0)