-
Notifications
You must be signed in to change notification settings - Fork 0
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
refactor and clean up encoding #7
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
import "./ITransparentUpgradeableProxy.sol"; | ||
|
||
interface IProxyAdmin { | ||
function getProxyImplementation(ITransparentUpgradeableProxy proxy) external view returns (address); | ||
|
||
function getProxyAdmin(ITransparentUpgradeableProxy proxy) external view returns (address); | ||
|
||
function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) external; | ||
|
||
function upgrade(ITransparentUpgradeableProxy proxy, address implementation) external; | ||
|
||
function upgradeAndCall(ITransparentUpgradeableProxy proxy, address implementation, bytes memory data) | ||
external | ||
payable; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
interface ITransparentUpgradeableProxy { | ||
function admin() external view returns (address); | ||
|
||
function implementation() external view returns (address); | ||
|
||
function changeAdmin(address) external; | ||
|
||
function upgradeTo(address) external; | ||
|
||
function upgradeToAndCall(address, bytes memory) external payable; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
interface IUpgradeableBeacon { | ||
function implementation() external view returns (address); | ||
|
||
function upgradeTo(address newImplementation) external; | ||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity ^0.8.12; | ||
|
||
// import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
// import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; | ||
|
||
import "../interfaces/IMultiSend.sol"; | ||
import "../interfaces/ISafe.sol"; | ||
import "../interfaces/IProxyAdmin.sol"; | ||
import "../interfaces/IUpgradeableBeacon.sol"; | ||
|
||
struct MultisigCall { | ||
address to; | ||
uint256 value; | ||
bytes data; | ||
} | ||
|
||
library Encode { | ||
/// Used for state vars: | ||
/// | ||
/// uint idx; | ||
/// mapping(uint => MultisigCall[]) map; | ||
bytes32 internal constant IDX_SLOT = keccak256("IDX_SLOT"); | ||
bytes32 internal constant MAP_SLOT = keccak256("MAP_SLOT"); | ||
|
||
/// Used to describe calls from a Gnosis Safe | ||
enum Operation { | ||
Call, | ||
DelegateCall | ||
} | ||
|
||
/// Constants for Safe.execTransaction inputs we don't usee | ||
uint256 constant SAFE_TX_GAS = 0; | ||
uint256 constant BASE_GAS = 0; | ||
uint256 constant GAS_PRICE = 0; | ||
address constant GAS_TOKEN = address(uint160(0)); | ||
address payable constant REFUND_RECEIVER = payable(address(uint160(0))); | ||
|
||
/// Dummy types and variables to facilitate syntax, e.g: `Encode.proxyAdmin.upgrade(...)` | ||
enum EncProxyAdmin { | ||
A | ||
} | ||
enum EncUpgradeableBeacon { | ||
A | ||
} | ||
enum EncGnosisSafe { | ||
A | ||
} | ||
|
||
EncProxyAdmin internal constant proxyAdmin = EncProxyAdmin.A; | ||
EncUpgradeableBeacon internal constant upgradeableBeacon = EncUpgradeableBeacon.A; | ||
EncGnosisSafe internal constant gnosisSafe = EncGnosisSafe.A; | ||
|
||
/// @dev Creates a new, clean `MultisigCall[] storage` pointer, guaranteeing | ||
/// any previous pointers will not be overwritten. | ||
/// Since we're in a library, we have to use assembly+slot pointers, but the | ||
/// high level version of this function equates to: | ||
/// | ||
/// uint _idx = storage.idx; | ||
/// storage.idx++; | ||
/// MultisigCall[] storage calls = storage.map[_idx]; | ||
/// return calls; | ||
function newMultisigCalls() internal returns (MultisigCall[] storage) { | ||
bytes32 _IDX_SLOT = IDX_SLOT; | ||
bytes32 _MAP_SLOT = MAP_SLOT; | ||
|
||
uint256 idx; | ||
assembly { | ||
idx := sload(_IDX_SLOT) | ||
sstore(_IDX_SLOT, add(1, idx)) | ||
} | ||
|
||
// fn pointer indirection fools the compiler into letting us have | ||
// an uninitialized storage pointer | ||
function() pure returns (mapping(uint => MultisigCall[]) storage) fn; | ||
function() pure returns (uint) fn2 = func; | ||
assembly { | ||
fn := fn2 | ||
} | ||
mapping(uint256 => MultisigCall[]) storage map = fn(); | ||
assembly { | ||
map.slot := _MAP_SLOT | ||
} | ||
|
||
return map[idx]; | ||
} | ||
|
||
function func() internal pure returns (uint256) { | ||
return 0; | ||
} | ||
|
||
/// @dev Appends a call to a list of `MultisigCalls`, returning the original storage pointer | ||
/// to facilitate call chaining syntax, e.g: | ||
/// | ||
/// calls | ||
/// .append(...) | ||
/// .append(...) | ||
/// .append(...); | ||
function append(MultisigCall[] storage calls, address to, bytes memory data) | ||
internal | ||
returns (MultisigCall[] storage) | ||
{ | ||
calls.push(MultisigCall({to: to, value: 0, data: data})); | ||
|
||
return calls; | ||
} | ||
|
||
/// @dev Encodes a call to `ProxyAdmin.upgrade(proxy, impl)` | ||
function upgrade(EncProxyAdmin, address proxy, address impl) internal pure returns (bytes memory) { | ||
return abi.encodeCall(IProxyAdmin.upgrade, (ITransparentUpgradeableProxy(proxy), impl)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO nit but it feels like it would be more straightforward to leave abi.encodeCall(IProxyAdmin, to, params) but make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im not super sure what you're asking for, but this is less about how i can share examples if you want |
||
|
||
/// @dev Encodes a call to `UpgradeableBeacon.upgradeTo(newImpl)` | ||
function upgradeTo(EncUpgradeableBeacon, address newImpl) internal pure returns (bytes memory) { | ||
return abi.encodeCall(IUpgradeableBeacon.upgradeTo, (newImpl)); | ||
} | ||
|
||
/// @dev Encodes a call to `MultiSend.multiSend(data)` | ||
function multiSend(MultisigCall[] memory calls) internal pure returns (bytes memory) { | ||
bytes memory packedCalls = new bytes(0); | ||
|
||
for (uint256 i = 0; i < calls.length; i++) { | ||
packedCalls = abi.encodePacked( | ||
packedCalls, | ||
abi.encodePacked(uint8(0), calls[i].to, calls[i].value, uint256(calls[i].data.length), calls[i].data) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would normally link to https://github.com/safe-global/safe-smart-account/blob/main/contracts/libraries/MultiSend.sol#L20 for this gibberish xD |
||
); | ||
} | ||
|
||
return abi.encodeCall(IMultiSend.multiSend, packedCalls); | ||
} | ||
|
||
/// @dev Encodes a call to `Safe.execTransaction` | ||
function execTransaction(EncGnosisSafe, address from, address to, Operation op, bytes memory data) | ||
internal | ||
pure | ||
returns (bytes memory) | ||
{ | ||
return _encExecTranasction({from: from, to: to, op: op, value: 0, data: data}); | ||
} | ||
|
||
function _encExecTranasction(address from, address to, Operation op, uint256 value, bytes memory data) | ||
private | ||
pure | ||
returns (bytes memory) | ||
{ | ||
bytes1 v = bytes1(uint8(1)); | ||
bytes32 r = bytes32(uint256(uint160(from))); | ||
bytes32 s; | ||
bytes memory sig = abi.encodePacked(r, s, v); | ||
|
||
return abi.encodeCall( | ||
ISafe.execTransaction, | ||
(to, value, data, uint8(op), SAFE_TX_GAS, BASE_GAS, GAS_PRICE, GAS_TOKEN, REFUND_RECEIVER, sig) | ||
); | ||
} | ||
} |
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you likey?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sol devs would rather do this than just contribute to the compiler LMAO