Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discuss] feat: add exttload to vault #62

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .forge-snapshots/BinHookTest#testBurnSucceedsWithHook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
180732
180720
Original file line number Diff line number Diff line change
@@ -1 +1 @@
184900
184922
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137531
137556
2 changes: 1 addition & 1 deletion .forge-snapshots/BinHookTest#testMintSucceedsWithHook.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
331216
331204
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137002
136985
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1824
1818
Original file line number Diff line number Diff line change
@@ -1 +1 @@
32155
32143
Original file line number Diff line number Diff line change
@@ -1 +1 @@
30405
30373
Original file line number Diff line number Diff line change
@@ -1 +1 @@
146702
146680
Original file line number Diff line number Diff line change
@@ -1 +1 @@
294281
294263
2 changes: 1 addition & 1 deletion .forge-snapshots/BinPoolManagerTest#testGasBurnOneBin.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
130194
130177
2 changes: 1 addition & 1 deletion .forge-snapshots/BinPoolManagerTest#testGasDonate.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
119509
119453
Original file line number Diff line number Diff line change
@@ -1 +1 @@
976097
976031
Original file line number Diff line number Diff line change
@@ -1 +1 @@
338287
338221
Original file line number Diff line number Diff line change
@@ -1 +1 @@
341796
341730
Original file line number Diff line number Diff line change
@@ -1 +1 @@
144739
144673
Original file line number Diff line number Diff line change
@@ -1 +1 @@
179097
179053
Original file line number Diff line number Diff line change
@@ -1 +1 @@
185080
185036
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137535
137491
Original file line number Diff line number Diff line change
@@ -1 +1 @@
308275
308209
Original file line number Diff line number Diff line change
@@ -1 +1 @@
34487
34475
Original file line number Diff line number Diff line change
@@ -1 +1 @@
455
456
Original file line number Diff line number Diff line change
@@ -1 +1 @@
457
458
Original file line number Diff line number Diff line change
@@ -1 +1 @@
453
454
Original file line number Diff line number Diff line change
@@ -1 +1 @@
360023
359979
Original file line number Diff line number Diff line change
@@ -1 +1 @@
175191
175147
Original file line number Diff line number Diff line change
@@ -1 +1 @@
245111
245092
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#donateBothTokens.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
168607
168497
2 changes: 1 addition & 1 deletion .forge-snapshots/CLPoolManagerTest#gasDonateOneToken.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
112417
112332
Original file line number Diff line number Diff line change
@@ -1 +1 @@
137753
137731
Original file line number Diff line number Diff line change
@@ -1 +1 @@
170905
170883
Original file line number Diff line number Diff line change
@@ -1 +1 @@
157667
157645
Original file line number Diff line number Diff line change
@@ -1 +1 @@
31820
31842
2 changes: 1 addition & 1 deletion .forge-snapshots/ExtsloadTest#extsloadInBatch.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10654
10676
1 change: 1 addition & 0 deletions .forge-snapshots/ExtsloadTest#testExtsloadNSlot.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14460
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#Vault.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7124
7461
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#collectFee.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
25138
25135
Original file line number Diff line number Diff line change
@@ -1 +1 @@
81463
81428
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#lockSettledWhenFlashloan.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
121269
121297
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45005
44992
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#lockSettledWhenSwap.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
45004
44988
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#registerPoolManager.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
47916
47913
2 changes: 1 addition & 1 deletion .forge-snapshots/VaultTest#testLock_NoOp.snap
Original file line number Diff line number Diff line change
@@ -1 +1 @@
33072
33050
19 changes: 19 additions & 0 deletions src/Extsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,25 @@ abstract contract Extsload is IExtsload {
}
}

/// @inheritdoc IExtsload
function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes memory) {
assembly ("memory-safe") {
// The abi offset of dynamic array in the returndata is 32.
mstore(0, 0x20)
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
mstore(0x20, shl(5, nSlots))
let end := add(0x40, shl(5, nSlots))
for { let memptr := 0x40 } 1 {} {
mstore(memptr, sload(startSlot))
memptr := add(memptr, 0x20)
startSlot := add(startSlot, 1)
if iszero(lt(memptr, end)) { break }
}
// The end offset is also the length of the returndata.
return(0, end)
}
}

/// @inheritdoc IExtsload
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
// since the function is external and enters a new call context and exits right
Expand Down
40 changes: 40 additions & 0 deletions src/Exttload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright (C) 2024 PancakeSwap
pragma solidity ^0.8.24;

import {IExttload} from "./interfaces/IExttload.sol";

/// @notice Enables public transient storage access for efficient state retrieval by external contracts.
/// https://eips.ethereum.org/EIPS/eip-2330#rationale
abstract contract Exttload is IExttload {
/// @inheritdoc IExttload
function exttload(bytes32 slot) external view returns (bytes32) {
assembly ("memory-safe") {
mstore(0, tload(slot))
return(0, 0x20)
}
}

/// @inheritdoc IExttload
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory) {
// since the function is external and enters a new call context and exits right
// after execution, Solidity's memory management convention can be disregarded
// and a direct slice of memory can be returned
assembly ("memory-safe") {
// Copy the abi offset of dynamic array and the length of the array to memory.
calldatacopy(0, 0x04, 0x40)
// A left bit-shift of 5 is equivalent to multiplying by 32 but costs less gas.
let end := add(0x40, shl(5, slots.length))
let calldataptr := slots.offset
// Return values will start at 64 while calldata offset is 68.
for { let memptr := 0x40 } 1 {} {
mstore(memptr, tload(calldataload(calldataptr)))
memptr := add(memptr, 0x20)
calldataptr := add(calldataptr, 0x20)
if iszero(lt(memptr, end)) { break }
}
// The end offset is also the length of the returndata.
return(0, end)
}
}
}
3 changes: 2 additions & 1 deletion src/Vault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ import {ILockCallback} from "./interfaces/ILockCallback.sol";
import {SafeCast} from "./libraries/SafeCast.sol";
import {VaultReserves} from "./libraries/VaultReserves.sol";
import {VaultToken} from "./VaultToken.sol";
import {Exttload} from "./Exttload.sol";

contract Vault is IVault, VaultToken, Ownable {
contract Vault is IVault, VaultToken, Ownable, Exttload {
using SafeCast for *;
using PoolIdLibrary for PoolKey;
using CurrencyLibrary for Currency;
Expand Down
6 changes: 6 additions & 0 deletions src/interfaces/IExtsload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ interface IExtsload {
/// @return value The value of the slot as bytes32
function extsload(bytes32 slot) external view returns (bytes32 value);

/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to start sloading from
/// @param nSlots Number of slots to load into return value
/// @return value The value of the sload-ed slots concatenated as dynamic bytes
function extsload(bytes32 slot, uint256 nSlots) external view returns (bytes memory value);

/// @notice Called by external contracts to access sparse pool state
/// @param slots List of slots to SLOAD from.
/// @return values List of loaded values.
Expand Down
14 changes: 14 additions & 0 deletions src/interfaces/IExttload.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IExttload {
/// @notice Called by external contracts to access transient storage of the contract
/// @param slot Key of slot to tload
/// @return value The value of the slot as bytes32
function exttload(bytes32 slot) external view returns (bytes32 value);

/// @notice Called by external contracts to access sparse transient pool state
/// @param slots List of slots to tload
/// @return values List of loaded values
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
}
3 changes: 2 additions & 1 deletion src/interfaces/IVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {IPoolManager} from "./IPoolManager.sol";
import {IVaultToken} from "./IVaultToken.sol";
import {IExttload} from "./IExttload.sol";

interface IVault is IVaultToken {
interface IVault is IVaultToken, IExttload {
event PoolManagerRegistered(address indexed poolManager);

/// @notice Thrown when a function is not called by a pool manager
Expand Down
17 changes: 17 additions & 0 deletions test/Extsload.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,23 @@ contract ExtsloadTest is Test, GasSnapshot {
assertEq(abi.encode(slot3), abi.encode(address(0xabcd)));
}

function testExtsloadNSlot() public {
snapStart("ExtsloadTest#testExtsloadNSlot");
bytes memory data = poolManager.extsload(bytes32(uint256(0x00)), 4);
snapEnd();

address owner;
address protocolFeeController;
assembly {
owner := mload(add(data, 32))
// slot 0x01 and 0x02 are mapping so skip for now
protocolFeeController := mload(add(data, 128))
}

assertEq(owner, address(this));
assertEq(protocolFeeController, address(0xabcd));
}

function testExtsloadInBatch() public {
bytes32[] memory slots = new bytes32[](2);
slots[0] = 0x00;
Expand Down
Loading
Loading